diff options
Diffstat (limited to 'fs')
320 files changed, 9330 insertions, 7912 deletions
diff --git a/fs/9p/Makefile b/fs/9p/Makefile index 1a940ec7af61..91fba025fcbe 100644 --- a/fs/9p/Makefile +++ b/fs/9p/Makefile | |||
@@ -8,6 +8,8 @@ obj-$(CONFIG_9P_FS) := 9p.o | |||
8 | vfs_dir.o \ | 8 | vfs_dir.o \ |
9 | vfs_dentry.o \ | 9 | vfs_dentry.o \ |
10 | v9fs.o \ | 10 | v9fs.o \ |
11 | fid.o | 11 | fid.o \ |
12 | xattr.o \ | ||
13 | xattr_user.o | ||
12 | 14 | ||
13 | 9p-$(CONFIG_9P_FSCACHE) += cache.o | 15 | 9p-$(CONFIG_9P_FSCACHE) += cache.o |
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 7317b39b2815..358563689064 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
@@ -97,6 +97,34 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, u32 uid, int any) | |||
97 | return ret; | 97 | return ret; |
98 | } | 98 | } |
99 | 99 | ||
100 | /* | ||
101 | * We need to hold v9ses->rename_sem as long as we hold references | ||
102 | * to returned path array. Array element contain pointers to | ||
103 | * dentry names. | ||
104 | */ | ||
105 | static int build_path_from_dentry(struct v9fs_session_info *v9ses, | ||
106 | struct dentry *dentry, char ***names) | ||
107 | { | ||
108 | int n = 0, i; | ||
109 | char **wnames; | ||
110 | struct dentry *ds; | ||
111 | |||
112 | for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent) | ||
113 | n++; | ||
114 | |||
115 | wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL); | ||
116 | if (!wnames) | ||
117 | goto err_out; | ||
118 | |||
119 | for (ds = dentry, i = (n-1); i >= 0; i--, ds = ds->d_parent) | ||
120 | wnames[i] = (char *)ds->d_name.name; | ||
121 | |||
122 | *names = wnames; | ||
123 | return n; | ||
124 | err_out: | ||
125 | return -ENOMEM; | ||
126 | } | ||
127 | |||
100 | /** | 128 | /** |
101 | * v9fs_fid_lookup - lookup for a fid, try to walk if not found | 129 | * v9fs_fid_lookup - lookup for a fid, try to walk if not found |
102 | * @dentry: dentry to look for fid in | 130 | * @dentry: dentry to look for fid in |
@@ -112,7 +140,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) | |||
112 | int i, n, l, clone, any, access; | 140 | int i, n, l, clone, any, access; |
113 | u32 uid; | 141 | u32 uid; |
114 | struct p9_fid *fid, *old_fid = NULL; | 142 | struct p9_fid *fid, *old_fid = NULL; |
115 | struct dentry *d, *ds; | 143 | struct dentry *ds; |
116 | struct v9fs_session_info *v9ses; | 144 | struct v9fs_session_info *v9ses; |
117 | char **wnames, *uname; | 145 | char **wnames, *uname; |
118 | 146 | ||
@@ -139,49 +167,62 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) | |||
139 | fid = v9fs_fid_find(dentry, uid, any); | 167 | fid = v9fs_fid_find(dentry, uid, any); |
140 | if (fid) | 168 | if (fid) |
141 | return fid; | 169 | return fid; |
142 | 170 | /* | |
171 | * we don't have a matching fid. To do a TWALK we need | ||
172 | * parent fid. We need to prevent rename when we want to | ||
173 | * look at the parent. | ||
174 | */ | ||
175 | down_read(&v9ses->rename_sem); | ||
143 | ds = dentry->d_parent; | 176 | ds = dentry->d_parent; |
144 | fid = v9fs_fid_find(ds, uid, any); | 177 | fid = v9fs_fid_find(ds, uid, any); |
145 | if (!fid) { /* walk from the root */ | 178 | if (fid) { |
146 | n = 0; | 179 | /* Found the parent fid do a lookup with that */ |
147 | for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent) | 180 | fid = p9_client_walk(fid, 1, (char **)&dentry->d_name.name, 1); |
148 | n++; | 181 | goto fid_out; |
182 | } | ||
183 | up_read(&v9ses->rename_sem); | ||
149 | 184 | ||
150 | fid = v9fs_fid_find(ds, uid, any); | 185 | /* start from the root and try to do a lookup */ |
151 | if (!fid) { /* the user is not attached to the fs yet */ | 186 | fid = v9fs_fid_find(dentry->d_sb->s_root, uid, any); |
152 | if (access == V9FS_ACCESS_SINGLE) | 187 | if (!fid) { |
153 | return ERR_PTR(-EPERM); | 188 | /* the user is not attached to the fs yet */ |
189 | if (access == V9FS_ACCESS_SINGLE) | ||
190 | return ERR_PTR(-EPERM); | ||
154 | 191 | ||
155 | if (v9fs_proto_dotu(v9ses)) | 192 | if (v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) |
156 | uname = NULL; | 193 | uname = NULL; |
157 | else | 194 | else |
158 | uname = v9ses->uname; | 195 | uname = v9ses->uname; |
159 | 196 | ||
160 | fid = p9_client_attach(v9ses->clnt, NULL, uname, uid, | 197 | fid = p9_client_attach(v9ses->clnt, NULL, uname, uid, |
161 | v9ses->aname); | 198 | v9ses->aname); |
162 | 199 | if (IS_ERR(fid)) | |
163 | if (IS_ERR(fid)) | 200 | return fid; |
164 | return fid; | ||
165 | |||
166 | v9fs_fid_add(ds, fid); | ||
167 | } | ||
168 | } else /* walk from the parent */ | ||
169 | n = 1; | ||
170 | 201 | ||
171 | if (ds == dentry) | 202 | v9fs_fid_add(dentry->d_sb->s_root, fid); |
203 | } | ||
204 | /* If we are root ourself just return that */ | ||
205 | if (dentry->d_sb->s_root == dentry) | ||
172 | return fid; | 206 | return fid; |
173 | 207 | /* | |
174 | wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL); | 208 | * Do a multipath walk with attached root. |
175 | if (!wnames) | 209 | * When walking parent we need to make sure we |
176 | return ERR_PTR(-ENOMEM); | 210 | * don't have a parallel rename happening |
177 | 211 | */ | |
178 | for (d = dentry, i = (n-1); i >= 0; i--, d = d->d_parent) | 212 | down_read(&v9ses->rename_sem); |
179 | wnames[i] = (char *) d->d_name.name; | 213 | n = build_path_from_dentry(v9ses, dentry, &wnames); |
180 | 214 | if (n < 0) { | |
215 | fid = ERR_PTR(n); | ||
216 | goto err_out; | ||
217 | } | ||
181 | clone = 1; | 218 | clone = 1; |
182 | i = 0; | 219 | i = 0; |
183 | while (i < n) { | 220 | while (i < n) { |
184 | l = min(n - i, P9_MAXWELEM); | 221 | l = min(n - i, P9_MAXWELEM); |
222 | /* | ||
223 | * We need to hold rename lock when doing a multipath | ||
224 | * walk to ensure none of the patch component change | ||
225 | */ | ||
185 | fid = p9_client_walk(fid, l, &wnames[i], clone); | 226 | fid = p9_client_walk(fid, l, &wnames[i], clone); |
186 | if (IS_ERR(fid)) { | 227 | if (IS_ERR(fid)) { |
187 | if (old_fid) { | 228 | if (old_fid) { |
@@ -193,15 +234,17 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) | |||
193 | p9_client_clunk(old_fid); | 234 | p9_client_clunk(old_fid); |
194 | } | 235 | } |
195 | kfree(wnames); | 236 | kfree(wnames); |
196 | return fid; | 237 | goto err_out; |
197 | } | 238 | } |
198 | old_fid = fid; | 239 | old_fid = fid; |
199 | i += l; | 240 | i += l; |
200 | clone = 0; | 241 | clone = 0; |
201 | } | 242 | } |
202 | |||
203 | kfree(wnames); | 243 | kfree(wnames); |
244 | fid_out: | ||
204 | v9fs_fid_add(dentry, fid); | 245 | v9fs_fid_add(dentry, fid); |
246 | err_out: | ||
247 | up_read(&v9ses->rename_sem); | ||
205 | return fid; | 248 | return fid; |
206 | } | 249 | } |
207 | 250 | ||
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index f8b86e92cd66..38dc0e067599 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
@@ -237,6 +237,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, | |||
237 | __putname(v9ses->uname); | 237 | __putname(v9ses->uname); |
238 | return ERR_PTR(-ENOMEM); | 238 | return ERR_PTR(-ENOMEM); |
239 | } | 239 | } |
240 | init_rwsem(&v9ses->rename_sem); | ||
240 | 241 | ||
241 | rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY); | 242 | rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY); |
242 | if (rc) { | 243 | if (rc) { |
@@ -278,7 +279,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, | |||
278 | v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ; | 279 | v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ; |
279 | 280 | ||
280 | /* for legacy mode, fall back to V9FS_ACCESS_ANY */ | 281 | /* for legacy mode, fall back to V9FS_ACCESS_ANY */ |
281 | if (!v9fs_proto_dotu(v9ses) && | 282 | if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) && |
282 | ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) { | 283 | ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) { |
283 | 284 | ||
284 | v9ses->flags &= ~V9FS_ACCESS_MASK; | 285 | v9ses->flags &= ~V9FS_ACCESS_MASK; |
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index bec4d0bcb458..4c963c9fc41f 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h | |||
@@ -104,6 +104,7 @@ struct v9fs_session_info { | |||
104 | struct p9_client *clnt; /* 9p client */ | 104 | struct p9_client *clnt; /* 9p client */ |
105 | struct list_head slist; /* list of sessions registered with v9fs */ | 105 | struct list_head slist; /* list of sessions registered with v9fs */ |
106 | struct backing_dev_info bdi; | 106 | struct backing_dev_info bdi; |
107 | struct rw_semaphore rename_sem; | ||
107 | }; | 108 | }; |
108 | 109 | ||
109 | struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, | 110 | struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, |
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 32ef4009d030..f47c6bbb01b3 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h | |||
@@ -55,6 +55,7 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode); | |||
55 | void v9fs_clear_inode(struct inode *inode); | 55 | void v9fs_clear_inode(struct inode *inode); |
56 | ino_t v9fs_qid2ino(struct p9_qid *qid); | 56 | ino_t v9fs_qid2ino(struct p9_qid *qid); |
57 | void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); | 57 | void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); |
58 | void v9fs_stat2inode_dotl(struct p9_stat_dotl *, struct inode *); | ||
58 | int v9fs_dir_release(struct inode *inode, struct file *filp); | 59 | int v9fs_dir_release(struct inode *inode, struct file *filp); |
59 | int v9fs_file_open(struct inode *inode, struct file *file); | 60 | int v9fs_file_open(struct inode *inode, struct file *file); |
60 | void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); | 61 | void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); |
diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index d61e3b28ce37..16c8a2a98c1b 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c | |||
@@ -87,29 +87,19 @@ static void p9stat_init(struct p9_wstat *stbuf) | |||
87 | } | 87 | } |
88 | 88 | ||
89 | /** | 89 | /** |
90 | * v9fs_dir_readdir - read a directory | 90 | * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir |
91 | * @filp: opened file structure | 91 | * @filp: opened file structure |
92 | * @dirent: directory structure ??? | 92 | * @buflen: Length in bytes of buffer to allocate |
93 | * @filldir: function to populate directory structure ??? | ||
94 | * | 93 | * |
95 | */ | 94 | */ |
96 | 95 | ||
97 | static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | 96 | static int v9fs_alloc_rdir_buf(struct file *filp, int buflen) |
98 | { | 97 | { |
99 | int over; | ||
100 | struct p9_wstat st; | ||
101 | int err = 0; | ||
102 | struct p9_fid *fid; | ||
103 | int buflen; | ||
104 | int reclen = 0; | ||
105 | struct p9_rdir *rdir; | 98 | struct p9_rdir *rdir; |
99 | struct p9_fid *fid; | ||
100 | int err = 0; | ||
106 | 101 | ||
107 | P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); | ||
108 | fid = filp->private_data; | 102 | fid = filp->private_data; |
109 | |||
110 | buflen = fid->clnt->msize - P9_IOHDRSZ; | ||
111 | |||
112 | /* allocate rdir on demand */ | ||
113 | if (!fid->rdir) { | 103 | if (!fid->rdir) { |
114 | rdir = kmalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL); | 104 | rdir = kmalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL); |
115 | 105 | ||
@@ -128,6 +118,36 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
128 | spin_unlock(&filp->f_dentry->d_lock); | 118 | spin_unlock(&filp->f_dentry->d_lock); |
129 | kfree(rdir); | 119 | kfree(rdir); |
130 | } | 120 | } |
121 | exit: | ||
122 | return err; | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * v9fs_dir_readdir - read a directory | ||
127 | * @filp: opened file structure | ||
128 | * @dirent: directory structure ??? | ||
129 | * @filldir: function to populate directory structure ??? | ||
130 | * | ||
131 | */ | ||
132 | |||
133 | static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | ||
134 | { | ||
135 | int over; | ||
136 | struct p9_wstat st; | ||
137 | int err = 0; | ||
138 | struct p9_fid *fid; | ||
139 | int buflen; | ||
140 | int reclen = 0; | ||
141 | struct p9_rdir *rdir; | ||
142 | |||
143 | P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); | ||
144 | fid = filp->private_data; | ||
145 | |||
146 | buflen = fid->clnt->msize - P9_IOHDRSZ; | ||
147 | |||
148 | err = v9fs_alloc_rdir_buf(filp, buflen); | ||
149 | if (err) | ||
150 | goto exit; | ||
131 | rdir = (struct p9_rdir *) fid->rdir; | 151 | rdir = (struct p9_rdir *) fid->rdir; |
132 | 152 | ||
133 | err = mutex_lock_interruptible(&rdir->mutex); | 153 | err = mutex_lock_interruptible(&rdir->mutex); |
@@ -146,7 +166,7 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
146 | while (rdir->head < rdir->tail) { | 166 | while (rdir->head < rdir->tail) { |
147 | p9stat_init(&st); | 167 | p9stat_init(&st); |
148 | err = p9stat_read(rdir->buf + rdir->head, | 168 | err = p9stat_read(rdir->buf + rdir->head, |
149 | buflen - rdir->head, &st, | 169 | rdir->tail - rdir->head, &st, |
150 | fid->clnt->proto_version); | 170 | fid->clnt->proto_version); |
151 | if (err) { | 171 | if (err) { |
152 | P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); | 172 | P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); |
@@ -176,6 +196,88 @@ exit: | |||
176 | return err; | 196 | return err; |
177 | } | 197 | } |
178 | 198 | ||
199 | /** | ||
200 | * v9fs_dir_readdir_dotl - read a directory | ||
201 | * @filp: opened file structure | ||
202 | * @dirent: buffer to fill dirent structures | ||
203 | * @filldir: function to populate dirent structures | ||
204 | * | ||
205 | */ | ||
206 | static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent, | ||
207 | filldir_t filldir) | ||
208 | { | ||
209 | int over; | ||
210 | int err = 0; | ||
211 | struct p9_fid *fid; | ||
212 | int buflen; | ||
213 | struct p9_rdir *rdir; | ||
214 | struct p9_dirent curdirent; | ||
215 | u64 oldoffset = 0; | ||
216 | |||
217 | P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); | ||
218 | fid = filp->private_data; | ||
219 | |||
220 | buflen = fid->clnt->msize - P9_READDIRHDRSZ; | ||
221 | |||
222 | err = v9fs_alloc_rdir_buf(filp, buflen); | ||
223 | if (err) | ||
224 | goto exit; | ||
225 | rdir = (struct p9_rdir *) fid->rdir; | ||
226 | |||
227 | err = mutex_lock_interruptible(&rdir->mutex); | ||
228 | if (err) | ||
229 | return err; | ||
230 | |||
231 | while (err == 0) { | ||
232 | if (rdir->tail == rdir->head) { | ||
233 | err = p9_client_readdir(fid, rdir->buf, buflen, | ||
234 | filp->f_pos); | ||
235 | if (err <= 0) | ||
236 | goto unlock_and_exit; | ||
237 | |||
238 | rdir->head = 0; | ||
239 | rdir->tail = err; | ||
240 | } | ||
241 | |||
242 | while (rdir->head < rdir->tail) { | ||
243 | |||
244 | err = p9dirent_read(rdir->buf + rdir->head, | ||
245 | buflen - rdir->head, &curdirent, | ||
246 | fid->clnt->proto_version); | ||
247 | if (err < 0) { | ||
248 | P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err); | ||
249 | err = -EIO; | ||
250 | goto unlock_and_exit; | ||
251 | } | ||
252 | |||
253 | /* d_off in dirent structure tracks the offset into | ||
254 | * the next dirent in the dir. However, filldir() | ||
255 | * expects offset into the current dirent. Hence | ||
256 | * while calling filldir send the offset from the | ||
257 | * previous dirent structure. | ||
258 | */ | ||
259 | over = filldir(dirent, curdirent.d_name, | ||
260 | strlen(curdirent.d_name), | ||
261 | oldoffset, v9fs_qid2ino(&curdirent.qid), | ||
262 | curdirent.d_type); | ||
263 | oldoffset = curdirent.d_off; | ||
264 | |||
265 | if (over) { | ||
266 | err = 0; | ||
267 | goto unlock_and_exit; | ||
268 | } | ||
269 | |||
270 | filp->f_pos = curdirent.d_off; | ||
271 | rdir->head += err; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | unlock_and_exit: | ||
276 | mutex_unlock(&rdir->mutex); | ||
277 | exit: | ||
278 | return err; | ||
279 | } | ||
280 | |||
179 | 281 | ||
180 | /** | 282 | /** |
181 | * v9fs_dir_release - close a directory | 283 | * v9fs_dir_release - close a directory |
@@ -207,7 +309,7 @@ const struct file_operations v9fs_dir_operations = { | |||
207 | const struct file_operations v9fs_dir_operations_dotl = { | 309 | const struct file_operations v9fs_dir_operations_dotl = { |
208 | .read = generic_read_dir, | 310 | .read = generic_read_dir, |
209 | .llseek = generic_file_llseek, | 311 | .llseek = generic_file_llseek, |
210 | .readdir = v9fs_dir_readdir, | 312 | .readdir = v9fs_dir_readdir_dotl, |
211 | .open = v9fs_file_open, | 313 | .open = v9fs_file_open, |
212 | .release = v9fs_dir_release, | 314 | .release = v9fs_dir_release, |
213 | }; | 315 | }; |
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 2bedc6c94fc2..e97c92bd6f16 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
@@ -59,9 +59,13 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
59 | struct p9_fid *fid; | 59 | struct p9_fid *fid; |
60 | int omode; | 60 | int omode; |
61 | 61 | ||
62 | P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p \n", inode, file); | 62 | P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file); |
63 | v9ses = v9fs_inode2v9ses(inode); | 63 | v9ses = v9fs_inode2v9ses(inode); |
64 | omode = v9fs_uflags2omode(file->f_flags, v9fs_proto_dotu(v9ses)); | 64 | if (v9fs_proto_dotl(v9ses)) |
65 | omode = file->f_flags; | ||
66 | else | ||
67 | omode = v9fs_uflags2omode(file->f_flags, | ||
68 | v9fs_proto_dotu(v9ses)); | ||
65 | fid = file->private_data; | 69 | fid = file->private_data; |
66 | if (!fid) { | 70 | if (!fid) { |
67 | fid = v9fs_fid_clone(file->f_path.dentry); | 71 | fid = v9fs_fid_clone(file->f_path.dentry); |
@@ -73,11 +77,12 @@ int v9fs_file_open(struct inode *inode, struct file *file) | |||
73 | p9_client_clunk(fid); | 77 | p9_client_clunk(fid); |
74 | return err; | 78 | return err; |
75 | } | 79 | } |
76 | if (omode & P9_OTRUNC) { | 80 | if (file->f_flags & O_TRUNC) { |
77 | i_size_write(inode, 0); | 81 | i_size_write(inode, 0); |
78 | inode->i_blocks = 0; | 82 | inode->i_blocks = 0; |
79 | } | 83 | } |
80 | if ((file->f_flags & O_APPEND) && (!v9fs_proto_dotu(v9ses))) | 84 | if ((file->f_flags & O_APPEND) && |
85 | (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses))) | ||
81 | generic_file_llseek(file, 0, SEEK_END); | 86 | generic_file_llseek(file, 0, SEEK_END); |
82 | } | 87 | } |
83 | 88 | ||
@@ -139,7 +144,7 @@ ssize_t | |||
139 | v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, | 144 | v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, |
140 | u64 offset) | 145 | u64 offset) |
141 | { | 146 | { |
142 | int n, total; | 147 | int n, total, size; |
143 | struct p9_fid *fid = filp->private_data; | 148 | struct p9_fid *fid = filp->private_data; |
144 | 149 | ||
145 | P9_DPRINTK(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", fid->fid, | 150 | P9_DPRINTK(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", fid->fid, |
@@ -147,6 +152,7 @@ v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, | |||
147 | 152 | ||
148 | n = 0; | 153 | n = 0; |
149 | total = 0; | 154 | total = 0; |
155 | size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; | ||
150 | do { | 156 | do { |
151 | n = p9_client_read(fid, data, udata, offset, count); | 157 | n = p9_client_read(fid, data, udata, offset, count); |
152 | if (n <= 0) | 158 | if (n <= 0) |
@@ -160,7 +166,7 @@ v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, | |||
160 | offset += n; | 166 | offset += n; |
161 | count -= n; | 167 | count -= n; |
162 | total += n; | 168 | total += n; |
163 | } while (count > 0 && n == (fid->clnt->msize - P9_IOHDRSZ)); | 169 | } while (count > 0 && n == size); |
164 | 170 | ||
165 | if (n < 0) | 171 | if (n < 0) |
166 | total = n; | 172 | total = n; |
@@ -183,11 +189,13 @@ v9fs_file_read(struct file *filp, char __user *udata, size_t count, | |||
183 | { | 189 | { |
184 | int ret; | 190 | int ret; |
185 | struct p9_fid *fid; | 191 | struct p9_fid *fid; |
192 | size_t size; | ||
186 | 193 | ||
187 | P9_DPRINTK(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset); | 194 | P9_DPRINTK(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset); |
188 | fid = filp->private_data; | 195 | fid = filp->private_data; |
189 | 196 | ||
190 | if (count > (fid->clnt->msize - P9_IOHDRSZ)) | 197 | size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; |
198 | if (count > size) | ||
191 | ret = v9fs_file_readn(filp, NULL, udata, count, *offset); | 199 | ret = v9fs_file_readn(filp, NULL, udata, count, *offset); |
192 | else | 200 | else |
193 | ret = p9_client_read(fid, NULL, udata, *offset, count); | 201 | ret = p9_client_read(fid, NULL, udata, *offset, count); |
@@ -224,9 +232,7 @@ v9fs_file_write(struct file *filp, const char __user * data, | |||
224 | fid = filp->private_data; | 232 | fid = filp->private_data; |
225 | clnt = fid->clnt; | 233 | clnt = fid->clnt; |
226 | 234 | ||
227 | rsize = fid->iounit; | 235 | rsize = fid->iounit ? fid->iounit : clnt->msize - P9_IOHDRSZ; |
228 | if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) | ||
229 | rsize = clnt->msize - P9_IOHDRSZ; | ||
230 | 236 | ||
231 | do { | 237 | do { |
232 | if (count < rsize) | 238 | if (count < rsize) |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 4331b3b5ee1c..6e94f3247cec 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/idr.h> | 35 | #include <linux/idr.h> |
36 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/xattr.h> | ||
38 | #include <net/9p/9p.h> | 39 | #include <net/9p/9p.h> |
39 | #include <net/9p/client.h> | 40 | #include <net/9p/client.h> |
40 | 41 | ||
@@ -42,6 +43,7 @@ | |||
42 | #include "v9fs_vfs.h" | 43 | #include "v9fs_vfs.h" |
43 | #include "fid.h" | 44 | #include "fid.h" |
44 | #include "cache.h" | 45 | #include "cache.h" |
46 | #include "xattr.h" | ||
45 | 47 | ||
46 | static const struct inode_operations v9fs_dir_inode_operations; | 48 | static const struct inode_operations v9fs_dir_inode_operations; |
47 | static const struct inode_operations v9fs_dir_inode_operations_dotu; | 49 | static const struct inode_operations v9fs_dir_inode_operations_dotu; |
@@ -236,6 +238,41 @@ void v9fs_destroy_inode(struct inode *inode) | |||
236 | #endif | 238 | #endif |
237 | 239 | ||
238 | /** | 240 | /** |
241 | * v9fs_get_fsgid_for_create - Helper function to get the gid for creating a | ||
242 | * new file system object. This checks the S_ISGID to determine the owning | ||
243 | * group of the new file system object. | ||
244 | */ | ||
245 | |||
246 | static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) | ||
247 | { | ||
248 | BUG_ON(dir_inode == NULL); | ||
249 | |||
250 | if (dir_inode->i_mode & S_ISGID) { | ||
251 | /* set_gid bit is set.*/ | ||
252 | return dir_inode->i_gid; | ||
253 | } | ||
254 | return current_fsgid(); | ||
255 | } | ||
256 | |||
257 | /** | ||
258 | * v9fs_dentry_from_dir_inode - helper function to get the dentry from | ||
259 | * dir inode. | ||
260 | * | ||
261 | */ | ||
262 | |||
263 | static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode) | ||
264 | { | ||
265 | struct dentry *dentry; | ||
266 | |||
267 | spin_lock(&dcache_lock); | ||
268 | /* Directory should have only one entry. */ | ||
269 | BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry)); | ||
270 | dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias); | ||
271 | spin_unlock(&dcache_lock); | ||
272 | return dentry; | ||
273 | } | ||
274 | |||
275 | /** | ||
239 | * v9fs_get_inode - helper function to setup an inode | 276 | * v9fs_get_inode - helper function to setup an inode |
240 | * @sb: superblock | 277 | * @sb: superblock |
241 | * @mode: mode to setup inode with | 278 | * @mode: mode to setup inode with |
@@ -267,7 +304,13 @@ struct inode *v9fs_get_inode(struct super_block *sb, int mode) | |||
267 | case S_IFBLK: | 304 | case S_IFBLK: |
268 | case S_IFCHR: | 305 | case S_IFCHR: |
269 | case S_IFSOCK: | 306 | case S_IFSOCK: |
270 | if (!v9fs_proto_dotu(v9ses)) { | 307 | if (v9fs_proto_dotl(v9ses)) { |
308 | inode->i_op = &v9fs_file_inode_operations_dotl; | ||
309 | inode->i_fop = &v9fs_file_operations_dotl; | ||
310 | } else if (v9fs_proto_dotu(v9ses)) { | ||
311 | inode->i_op = &v9fs_file_inode_operations; | ||
312 | inode->i_fop = &v9fs_file_operations; | ||
313 | } else { | ||
271 | P9_DPRINTK(P9_DEBUG_ERROR, | 314 | P9_DPRINTK(P9_DEBUG_ERROR, |
272 | "special files without extended mode\n"); | 315 | "special files without extended mode\n"); |
273 | err = -EINVAL; | 316 | err = -EINVAL; |
@@ -396,23 +439,14 @@ void v9fs_clear_inode(struct inode *inode) | |||
396 | #endif | 439 | #endif |
397 | } | 440 | } |
398 | 441 | ||
399 | /** | ||
400 | * v9fs_inode_from_fid - populate an inode by issuing a attribute request | ||
401 | * @v9ses: session information | ||
402 | * @fid: fid to issue attribute request for | ||
403 | * @sb: superblock on which to create inode | ||
404 | * | ||
405 | */ | ||
406 | |||
407 | static struct inode * | 442 | static struct inode * |
408 | v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, | 443 | v9fs_inode(struct v9fs_session_info *v9ses, struct p9_fid *fid, |
409 | struct super_block *sb) | 444 | struct super_block *sb) |
410 | { | 445 | { |
411 | int err, umode; | 446 | int err, umode; |
412 | struct inode *ret; | 447 | struct inode *ret = NULL; |
413 | struct p9_wstat *st; | 448 | struct p9_wstat *st; |
414 | 449 | ||
415 | ret = NULL; | ||
416 | st = p9_client_stat(fid); | 450 | st = p9_client_stat(fid); |
417 | if (IS_ERR(st)) | 451 | if (IS_ERR(st)) |
418 | return ERR_CAST(st); | 452 | return ERR_CAST(st); |
@@ -433,15 +467,62 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, | |||
433 | #endif | 467 | #endif |
434 | p9stat_free(st); | 468 | p9stat_free(st); |
435 | kfree(st); | 469 | kfree(st); |
436 | |||
437 | return ret; | 470 | return ret; |
438 | |||
439 | error: | 471 | error: |
440 | p9stat_free(st); | 472 | p9stat_free(st); |
441 | kfree(st); | 473 | kfree(st); |
442 | return ERR_PTR(err); | 474 | return ERR_PTR(err); |
443 | } | 475 | } |
444 | 476 | ||
477 | static struct inode * | ||
478 | v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, | ||
479 | struct super_block *sb) | ||
480 | { | ||
481 | struct inode *ret = NULL; | ||
482 | int err; | ||
483 | struct p9_stat_dotl *st; | ||
484 | |||
485 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); | ||
486 | if (IS_ERR(st)) | ||
487 | return ERR_CAST(st); | ||
488 | |||
489 | ret = v9fs_get_inode(sb, st->st_mode); | ||
490 | if (IS_ERR(ret)) { | ||
491 | err = PTR_ERR(ret); | ||
492 | goto error; | ||
493 | } | ||
494 | |||
495 | v9fs_stat2inode_dotl(st, ret); | ||
496 | ret->i_ino = v9fs_qid2ino(&st->qid); | ||
497 | #ifdef CONFIG_9P_FSCACHE | ||
498 | v9fs_vcookie_set_qid(ret, &st->qid); | ||
499 | v9fs_cache_inode_get_cookie(ret); | ||
500 | #endif | ||
501 | kfree(st); | ||
502 | return ret; | ||
503 | error: | ||
504 | kfree(st); | ||
505 | return ERR_PTR(err); | ||
506 | } | ||
507 | |||
508 | /** | ||
509 | * v9fs_inode_from_fid - Helper routine to populate an inode by | ||
510 | * issuing a attribute request | ||
511 | * @v9ses: session information | ||
512 | * @fid: fid to issue attribute request for | ||
513 | * @sb: superblock on which to create inode | ||
514 | * | ||
515 | */ | ||
516 | static inline struct inode * | ||
517 | v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, | ||
518 | struct super_block *sb) | ||
519 | { | ||
520 | if (v9fs_proto_dotl(v9ses)) | ||
521 | return v9fs_inode_dotl(v9ses, fid, sb); | ||
522 | else | ||
523 | return v9fs_inode(v9ses, fid, sb); | ||
524 | } | ||
525 | |||
445 | /** | 526 | /** |
446 | * v9fs_remove - helper function to remove files and directories | 527 | * v9fs_remove - helper function to remove files and directories |
447 | * @dir: directory inode that is being deleted | 528 | * @dir: directory inode that is being deleted |
@@ -563,6 +644,118 @@ error: | |||
563 | } | 644 | } |
564 | 645 | ||
565 | /** | 646 | /** |
647 | * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol. | ||
648 | * @dir: directory inode that is being created | ||
649 | * @dentry: dentry that is being deleted | ||
650 | * @mode: create permissions | ||
651 | * @nd: path information | ||
652 | * | ||
653 | */ | ||
654 | |||
655 | static int | ||
656 | v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, | ||
657 | struct nameidata *nd) | ||
658 | { | ||
659 | int err = 0; | ||
660 | char *name = NULL; | ||
661 | gid_t gid; | ||
662 | int flags; | ||
663 | struct v9fs_session_info *v9ses; | ||
664 | struct p9_fid *fid = NULL; | ||
665 | struct p9_fid *dfid, *ofid; | ||
666 | struct file *filp; | ||
667 | struct p9_qid qid; | ||
668 | struct inode *inode; | ||
669 | |||
670 | v9ses = v9fs_inode2v9ses(dir); | ||
671 | if (nd && nd->flags & LOOKUP_OPEN) | ||
672 | flags = nd->intent.open.flags - 1; | ||
673 | else | ||
674 | flags = O_RDWR; | ||
675 | |||
676 | name = (char *) dentry->d_name.name; | ||
677 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x " | ||
678 | "mode:0x%x\n", name, flags, mode); | ||
679 | |||
680 | dfid = v9fs_fid_lookup(dentry->d_parent); | ||
681 | if (IS_ERR(dfid)) { | ||
682 | err = PTR_ERR(dfid); | ||
683 | P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); | ||
684 | return err; | ||
685 | } | ||
686 | |||
687 | /* clone a fid to use for creation */ | ||
688 | ofid = p9_client_walk(dfid, 0, NULL, 1); | ||
689 | if (IS_ERR(ofid)) { | ||
690 | err = PTR_ERR(ofid); | ||
691 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | ||
692 | return err; | ||
693 | } | ||
694 | |||
695 | gid = v9fs_get_fsgid_for_create(dir); | ||
696 | err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); | ||
697 | if (err < 0) { | ||
698 | P9_DPRINTK(P9_DEBUG_VFS, | ||
699 | "p9_client_open_dotl failed in creat %d\n", | ||
700 | err); | ||
701 | goto error; | ||
702 | } | ||
703 | |||
704 | /* No need to populate the inode if we are not opening the file AND | ||
705 | * not in cached mode. | ||
706 | */ | ||
707 | if (!v9ses->cache && !(nd && nd->flags & LOOKUP_OPEN)) { | ||
708 | /* Not in cached mode. No need to populate inode with stat */ | ||
709 | dentry->d_op = &v9fs_dentry_operations; | ||
710 | p9_client_clunk(ofid); | ||
711 | d_instantiate(dentry, NULL); | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | /* Now walk from the parent so we can get an unopened fid. */ | ||
716 | fid = p9_client_walk(dfid, 1, &name, 1); | ||
717 | if (IS_ERR(fid)) { | ||
718 | err = PTR_ERR(fid); | ||
719 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); | ||
720 | fid = NULL; | ||
721 | goto error; | ||
722 | } | ||
723 | |||
724 | /* instantiate inode and assign the unopened fid to dentry */ | ||
725 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | ||
726 | if (IS_ERR(inode)) { | ||
727 | err = PTR_ERR(inode); | ||
728 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); | ||
729 | goto error; | ||
730 | } | ||
731 | dentry->d_op = &v9fs_cached_dentry_operations; | ||
732 | d_instantiate(dentry, inode); | ||
733 | err = v9fs_fid_add(dentry, fid); | ||
734 | if (err < 0) | ||
735 | goto error; | ||
736 | |||
737 | /* if we are opening a file, assign the open fid to the file */ | ||
738 | if (nd && nd->flags & LOOKUP_OPEN) { | ||
739 | filp = lookup_instantiate_filp(nd, dentry, v9fs_open_created); | ||
740 | if (IS_ERR(filp)) { | ||
741 | p9_client_clunk(ofid); | ||
742 | return PTR_ERR(filp); | ||
743 | } | ||
744 | filp->private_data = ofid; | ||
745 | } else | ||
746 | p9_client_clunk(ofid); | ||
747 | |||
748 | return 0; | ||
749 | |||
750 | error: | ||
751 | if (ofid) | ||
752 | p9_client_clunk(ofid); | ||
753 | if (fid) | ||
754 | p9_client_clunk(fid); | ||
755 | return err; | ||
756 | } | ||
757 | |||
758 | /** | ||
566 | * v9fs_vfs_create - VFS hook to create files | 759 | * v9fs_vfs_create - VFS hook to create files |
567 | * @dir: directory inode that is being created | 760 | * @dir: directory inode that is being created |
568 | * @dentry: dentry that is being deleted | 761 | * @dentry: dentry that is being deleted |
@@ -652,6 +845,83 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
652 | return err; | 845 | return err; |
653 | } | 846 | } |
654 | 847 | ||
848 | |||
849 | /** | ||
850 | * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory | ||
851 | * @dir: inode that is being unlinked | ||
852 | * @dentry: dentry that is being unlinked | ||
853 | * @mode: mode for new directory | ||
854 | * | ||
855 | */ | ||
856 | |||
857 | static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, | ||
858 | int mode) | ||
859 | { | ||
860 | int err; | ||
861 | struct v9fs_session_info *v9ses; | ||
862 | struct p9_fid *fid = NULL, *dfid = NULL; | ||
863 | gid_t gid; | ||
864 | char *name; | ||
865 | struct inode *inode; | ||
866 | struct p9_qid qid; | ||
867 | struct dentry *dir_dentry; | ||
868 | |||
869 | P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); | ||
870 | err = 0; | ||
871 | v9ses = v9fs_inode2v9ses(dir); | ||
872 | |||
873 | mode |= S_IFDIR; | ||
874 | dir_dentry = v9fs_dentry_from_dir_inode(dir); | ||
875 | dfid = v9fs_fid_lookup(dir_dentry); | ||
876 | if (IS_ERR(dfid)) { | ||
877 | err = PTR_ERR(dfid); | ||
878 | P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); | ||
879 | dfid = NULL; | ||
880 | goto error; | ||
881 | } | ||
882 | |||
883 | gid = v9fs_get_fsgid_for_create(dir); | ||
884 | if (gid < 0) { | ||
885 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n"); | ||
886 | goto error; | ||
887 | } | ||
888 | |||
889 | name = (char *) dentry->d_name.name; | ||
890 | err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); | ||
891 | if (err < 0) | ||
892 | goto error; | ||
893 | |||
894 | /* instantiate inode and assign the unopened fid to the dentry */ | ||
895 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { | ||
896 | fid = p9_client_walk(dfid, 1, &name, 1); | ||
897 | if (IS_ERR(fid)) { | ||
898 | err = PTR_ERR(fid); | ||
899 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", | ||
900 | err); | ||
901 | fid = NULL; | ||
902 | goto error; | ||
903 | } | ||
904 | |||
905 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | ||
906 | if (IS_ERR(inode)) { | ||
907 | err = PTR_ERR(inode); | ||
908 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", | ||
909 | err); | ||
910 | goto error; | ||
911 | } | ||
912 | dentry->d_op = &v9fs_cached_dentry_operations; | ||
913 | d_instantiate(dentry, inode); | ||
914 | err = v9fs_fid_add(dentry, fid); | ||
915 | if (err < 0) | ||
916 | goto error; | ||
917 | fid = NULL; | ||
918 | } | ||
919 | error: | ||
920 | if (fid) | ||
921 | p9_client_clunk(fid); | ||
922 | return err; | ||
923 | } | ||
924 | |||
655 | /** | 925 | /** |
656 | * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode | 926 | * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode |
657 | * @dir: inode that is being walked from | 927 | * @dir: inode that is being walked from |
@@ -678,6 +948,7 @@ static struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, | |||
678 | 948 | ||
679 | sb = dir->i_sb; | 949 | sb = dir->i_sb; |
680 | v9ses = v9fs_inode2v9ses(dir); | 950 | v9ses = v9fs_inode2v9ses(dir); |
951 | /* We can walk d_parent because we hold the dir->i_mutex */ | ||
681 | dfid = v9fs_fid_lookup(dentry->d_parent); | 952 | dfid = v9fs_fid_lookup(dentry->d_parent); |
682 | if (IS_ERR(dfid)) | 953 | if (IS_ERR(dfid)) |
683 | return ERR_CAST(dfid); | 954 | return ERR_CAST(dfid); |
@@ -785,27 +1056,33 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
785 | goto clunk_olddir; | 1056 | goto clunk_olddir; |
786 | } | 1057 | } |
787 | 1058 | ||
1059 | down_write(&v9ses->rename_sem); | ||
788 | if (v9fs_proto_dotl(v9ses)) { | 1060 | if (v9fs_proto_dotl(v9ses)) { |
789 | retval = p9_client_rename(oldfid, newdirfid, | 1061 | retval = p9_client_rename(oldfid, newdirfid, |
790 | (char *) new_dentry->d_name.name); | 1062 | (char *) new_dentry->d_name.name); |
791 | if (retval != -ENOSYS) | 1063 | if (retval != -ENOSYS) |
792 | goto clunk_newdir; | 1064 | goto clunk_newdir; |
793 | } | 1065 | } |
1066 | if (old_dentry->d_parent != new_dentry->d_parent) { | ||
1067 | /* | ||
1068 | * 9P .u can only handle file rename in the same directory | ||
1069 | */ | ||
794 | 1070 | ||
795 | /* 9P can only handle file rename in the same directory */ | ||
796 | if (memcmp(&olddirfid->qid, &newdirfid->qid, sizeof(newdirfid->qid))) { | ||
797 | P9_DPRINTK(P9_DEBUG_ERROR, | 1071 | P9_DPRINTK(P9_DEBUG_ERROR, |
798 | "old dir and new dir are different\n"); | 1072 | "old dir and new dir are different\n"); |
799 | retval = -EXDEV; | 1073 | retval = -EXDEV; |
800 | goto clunk_newdir; | 1074 | goto clunk_newdir; |
801 | } | 1075 | } |
802 | |||
803 | v9fs_blank_wstat(&wstat); | 1076 | v9fs_blank_wstat(&wstat); |
804 | wstat.muid = v9ses->uname; | 1077 | wstat.muid = v9ses->uname; |
805 | wstat.name = (char *) new_dentry->d_name.name; | 1078 | wstat.name = (char *) new_dentry->d_name.name; |
806 | retval = p9_client_wstat(oldfid, &wstat); | 1079 | retval = p9_client_wstat(oldfid, &wstat); |
807 | 1080 | ||
808 | clunk_newdir: | 1081 | clunk_newdir: |
1082 | if (!retval) | ||
1083 | /* successful rename */ | ||
1084 | d_move(old_dentry, new_dentry); | ||
1085 | up_write(&v9ses->rename_sem); | ||
809 | p9_client_clunk(newdirfid); | 1086 | p9_client_clunk(newdirfid); |
810 | 1087 | ||
811 | clunk_olddir: | 1088 | clunk_olddir: |
@@ -853,6 +1130,42 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
853 | return 0; | 1130 | return 0; |
854 | } | 1131 | } |
855 | 1132 | ||
1133 | static int | ||
1134 | v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, | ||
1135 | struct kstat *stat) | ||
1136 | { | ||
1137 | int err; | ||
1138 | struct v9fs_session_info *v9ses; | ||
1139 | struct p9_fid *fid; | ||
1140 | struct p9_stat_dotl *st; | ||
1141 | |||
1142 | P9_DPRINTK(P9_DEBUG_VFS, "dentry: %p\n", dentry); | ||
1143 | err = -EPERM; | ||
1144 | v9ses = v9fs_inode2v9ses(dentry->d_inode); | ||
1145 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) | ||
1146 | return simple_getattr(mnt, dentry, stat); | ||
1147 | |||
1148 | fid = v9fs_fid_lookup(dentry); | ||
1149 | if (IS_ERR(fid)) | ||
1150 | return PTR_ERR(fid); | ||
1151 | |||
1152 | /* Ask for all the fields in stat structure. Server will return | ||
1153 | * whatever it supports | ||
1154 | */ | ||
1155 | |||
1156 | st = p9_client_getattr_dotl(fid, P9_STATS_ALL); | ||
1157 | if (IS_ERR(st)) | ||
1158 | return PTR_ERR(st); | ||
1159 | |||
1160 | v9fs_stat2inode_dotl(st, dentry->d_inode); | ||
1161 | generic_fillattr(dentry->d_inode, stat); | ||
1162 | /* Change block size to what the server returned */ | ||
1163 | stat->blksize = st->st_blksize; | ||
1164 | |||
1165 | kfree(st); | ||
1166 | return 0; | ||
1167 | } | ||
1168 | |||
856 | /** | 1169 | /** |
857 | * v9fs_vfs_setattr - set file metadata | 1170 | * v9fs_vfs_setattr - set file metadata |
858 | * @dentry: file whose metadata to set | 1171 | * @dentry: file whose metadata to set |
@@ -903,6 +1216,49 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) | |||
903 | } | 1216 | } |
904 | 1217 | ||
905 | /** | 1218 | /** |
1219 | * v9fs_vfs_setattr_dotl - set file metadata | ||
1220 | * @dentry: file whose metadata to set | ||
1221 | * @iattr: metadata assignment structure | ||
1222 | * | ||
1223 | */ | ||
1224 | |||
1225 | static int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) | ||
1226 | { | ||
1227 | int retval; | ||
1228 | struct v9fs_session_info *v9ses; | ||
1229 | struct p9_fid *fid; | ||
1230 | struct p9_iattr_dotl p9attr; | ||
1231 | |||
1232 | P9_DPRINTK(P9_DEBUG_VFS, "\n"); | ||
1233 | |||
1234 | retval = inode_change_ok(dentry->d_inode, iattr); | ||
1235 | if (retval) | ||
1236 | return retval; | ||
1237 | |||
1238 | p9attr.valid = iattr->ia_valid; | ||
1239 | p9attr.mode = iattr->ia_mode; | ||
1240 | p9attr.uid = iattr->ia_uid; | ||
1241 | p9attr.gid = iattr->ia_gid; | ||
1242 | p9attr.size = iattr->ia_size; | ||
1243 | p9attr.atime_sec = iattr->ia_atime.tv_sec; | ||
1244 | p9attr.atime_nsec = iattr->ia_atime.tv_nsec; | ||
1245 | p9attr.mtime_sec = iattr->ia_mtime.tv_sec; | ||
1246 | p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec; | ||
1247 | |||
1248 | retval = -EPERM; | ||
1249 | v9ses = v9fs_inode2v9ses(dentry->d_inode); | ||
1250 | fid = v9fs_fid_lookup(dentry); | ||
1251 | if (IS_ERR(fid)) | ||
1252 | return PTR_ERR(fid); | ||
1253 | |||
1254 | retval = p9_client_setattr(fid, &p9attr); | ||
1255 | if (retval >= 0) | ||
1256 | retval = inode_setattr(dentry->d_inode, iattr); | ||
1257 | |||
1258 | return retval; | ||
1259 | } | ||
1260 | |||
1261 | /** | ||
906 | * v9fs_stat2inode - populate an inode structure with mistat info | 1262 | * v9fs_stat2inode - populate an inode structure with mistat info |
907 | * @stat: Plan 9 metadata (mistat) structure | 1263 | * @stat: Plan 9 metadata (mistat) structure |
908 | * @inode: inode to populate | 1264 | * @inode: inode to populate |
@@ -980,6 +1336,77 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, | |||
980 | } | 1336 | } |
981 | 1337 | ||
982 | /** | 1338 | /** |
1339 | * v9fs_stat2inode_dotl - populate an inode structure with stat info | ||
1340 | * @stat: stat structure | ||
1341 | * @inode: inode to populate | ||
1342 | * @sb: superblock of filesystem | ||
1343 | * | ||
1344 | */ | ||
1345 | |||
1346 | void | ||
1347 | v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) | ||
1348 | { | ||
1349 | |||
1350 | if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { | ||
1351 | inode->i_atime.tv_sec = stat->st_atime_sec; | ||
1352 | inode->i_atime.tv_nsec = stat->st_atime_nsec; | ||
1353 | inode->i_mtime.tv_sec = stat->st_mtime_sec; | ||
1354 | inode->i_mtime.tv_nsec = stat->st_mtime_nsec; | ||
1355 | inode->i_ctime.tv_sec = stat->st_ctime_sec; | ||
1356 | inode->i_ctime.tv_nsec = stat->st_ctime_nsec; | ||
1357 | inode->i_uid = stat->st_uid; | ||
1358 | inode->i_gid = stat->st_gid; | ||
1359 | inode->i_nlink = stat->st_nlink; | ||
1360 | inode->i_mode = stat->st_mode; | ||
1361 | inode->i_rdev = new_decode_dev(stat->st_rdev); | ||
1362 | |||
1363 | if ((S_ISBLK(inode->i_mode)) || (S_ISCHR(inode->i_mode))) | ||
1364 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | ||
1365 | |||
1366 | i_size_write(inode, stat->st_size); | ||
1367 | inode->i_blocks = stat->st_blocks; | ||
1368 | } else { | ||
1369 | if (stat->st_result_mask & P9_STATS_ATIME) { | ||
1370 | inode->i_atime.tv_sec = stat->st_atime_sec; | ||
1371 | inode->i_atime.tv_nsec = stat->st_atime_nsec; | ||
1372 | } | ||
1373 | if (stat->st_result_mask & P9_STATS_MTIME) { | ||
1374 | inode->i_mtime.tv_sec = stat->st_mtime_sec; | ||
1375 | inode->i_mtime.tv_nsec = stat->st_mtime_nsec; | ||
1376 | } | ||
1377 | if (stat->st_result_mask & P9_STATS_CTIME) { | ||
1378 | inode->i_ctime.tv_sec = stat->st_ctime_sec; | ||
1379 | inode->i_ctime.tv_nsec = stat->st_ctime_nsec; | ||
1380 | } | ||
1381 | if (stat->st_result_mask & P9_STATS_UID) | ||
1382 | inode->i_uid = stat->st_uid; | ||
1383 | if (stat->st_result_mask & P9_STATS_GID) | ||
1384 | inode->i_gid = stat->st_gid; | ||
1385 | if (stat->st_result_mask & P9_STATS_NLINK) | ||
1386 | inode->i_nlink = stat->st_nlink; | ||
1387 | if (stat->st_result_mask & P9_STATS_MODE) { | ||
1388 | inode->i_mode = stat->st_mode; | ||
1389 | if ((S_ISBLK(inode->i_mode)) || | ||
1390 | (S_ISCHR(inode->i_mode))) | ||
1391 | init_special_inode(inode, inode->i_mode, | ||
1392 | inode->i_rdev); | ||
1393 | } | ||
1394 | if (stat->st_result_mask & P9_STATS_RDEV) | ||
1395 | inode->i_rdev = new_decode_dev(stat->st_rdev); | ||
1396 | if (stat->st_result_mask & P9_STATS_SIZE) | ||
1397 | i_size_write(inode, stat->st_size); | ||
1398 | if (stat->st_result_mask & P9_STATS_BLOCKS) | ||
1399 | inode->i_blocks = stat->st_blocks; | ||
1400 | } | ||
1401 | if (stat->st_result_mask & P9_STATS_GEN) | ||
1402 | inode->i_generation = stat->st_gen; | ||
1403 | |||
1404 | /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION | ||
1405 | * because the inode structure does not have fields for them. | ||
1406 | */ | ||
1407 | } | ||
1408 | |||
1409 | /** | ||
983 | * v9fs_qid2ino - convert qid into inode number | 1410 | * v9fs_qid2ino - convert qid into inode number |
984 | * @qid: qid to hash | 1411 | * @qid: qid to hash |
985 | * | 1412 | * |
@@ -1022,7 +1449,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | |||
1022 | if (IS_ERR(fid)) | 1449 | if (IS_ERR(fid)) |
1023 | return PTR_ERR(fid); | 1450 | return PTR_ERR(fid); |
1024 | 1451 | ||
1025 | if (!v9fs_proto_dotu(v9ses)) | 1452 | if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) |
1026 | return -EBADF; | 1453 | return -EBADF; |
1027 | 1454 | ||
1028 | st = p9_client_stat(fid); | 1455 | st = p9_client_stat(fid); |
@@ -1128,6 +1555,99 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, | |||
1128 | } | 1555 | } |
1129 | 1556 | ||
1130 | /** | 1557 | /** |
1558 | * v9fs_vfs_symlink_dotl - helper function to create symlinks | ||
1559 | * @dir: directory inode containing symlink | ||
1560 | * @dentry: dentry for symlink | ||
1561 | * @symname: symlink data | ||
1562 | * | ||
1563 | * See Also: 9P2000.L RFC for more information | ||
1564 | * | ||
1565 | */ | ||
1566 | |||
1567 | static int | ||
1568 | v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, | ||
1569 | const char *symname) | ||
1570 | { | ||
1571 | struct v9fs_session_info *v9ses; | ||
1572 | struct p9_fid *dfid; | ||
1573 | struct p9_fid *fid = NULL; | ||
1574 | struct inode *inode; | ||
1575 | struct p9_qid qid; | ||
1576 | char *name; | ||
1577 | int err; | ||
1578 | gid_t gid; | ||
1579 | |||
1580 | name = (char *) dentry->d_name.name; | ||
1581 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_symlink_dotl : %lu,%s,%s\n", | ||
1582 | dir->i_ino, name, symname); | ||
1583 | v9ses = v9fs_inode2v9ses(dir); | ||
1584 | |||
1585 | dfid = v9fs_fid_lookup(dentry->d_parent); | ||
1586 | if (IS_ERR(dfid)) { | ||
1587 | err = PTR_ERR(dfid); | ||
1588 | P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); | ||
1589 | return err; | ||
1590 | } | ||
1591 | |||
1592 | gid = v9fs_get_fsgid_for_create(dir); | ||
1593 | |||
1594 | if (gid < 0) { | ||
1595 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_egid failed %d\n", gid); | ||
1596 | goto error; | ||
1597 | } | ||
1598 | |||
1599 | /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */ | ||
1600 | err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid); | ||
1601 | |||
1602 | if (err < 0) { | ||
1603 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err); | ||
1604 | goto error; | ||
1605 | } | ||
1606 | |||
1607 | if (v9ses->cache) { | ||
1608 | /* Now walk from the parent so we can get an unopened fid. */ | ||
1609 | fid = p9_client_walk(dfid, 1, &name, 1); | ||
1610 | if (IS_ERR(fid)) { | ||
1611 | err = PTR_ERR(fid); | ||
1612 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", | ||
1613 | err); | ||
1614 | fid = NULL; | ||
1615 | goto error; | ||
1616 | } | ||
1617 | |||
1618 | /* instantiate inode and assign the unopened fid to dentry */ | ||
1619 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | ||
1620 | if (IS_ERR(inode)) { | ||
1621 | err = PTR_ERR(inode); | ||
1622 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", | ||
1623 | err); | ||
1624 | goto error; | ||
1625 | } | ||
1626 | dentry->d_op = &v9fs_cached_dentry_operations; | ||
1627 | d_instantiate(dentry, inode); | ||
1628 | err = v9fs_fid_add(dentry, fid); | ||
1629 | if (err < 0) | ||
1630 | goto error; | ||
1631 | fid = NULL; | ||
1632 | } else { | ||
1633 | /* Not in cached mode. No need to populate inode with stat */ | ||
1634 | inode = v9fs_get_inode(dir->i_sb, S_IFLNK); | ||
1635 | if (IS_ERR(inode)) { | ||
1636 | err = PTR_ERR(inode); | ||
1637 | goto error; | ||
1638 | } | ||
1639 | dentry->d_op = &v9fs_dentry_operations; | ||
1640 | d_instantiate(dentry, inode); | ||
1641 | } | ||
1642 | |||
1643 | error: | ||
1644 | if (fid) | ||
1645 | p9_client_clunk(fid); | ||
1646 | |||
1647 | return err; | ||
1648 | } | ||
1649 | |||
1650 | /** | ||
1131 | * v9fs_vfs_symlink - helper function to create symlinks | 1651 | * v9fs_vfs_symlink - helper function to create symlinks |
1132 | * @dir: directory inode containing symlink | 1652 | * @dir: directory inode containing symlink |
1133 | * @dentry: dentry for symlink | 1653 | * @dentry: dentry for symlink |
@@ -1186,6 +1706,76 @@ clunk_fid: | |||
1186 | } | 1706 | } |
1187 | 1707 | ||
1188 | /** | 1708 | /** |
1709 | * v9fs_vfs_link_dotl - create a hardlink for dotl | ||
1710 | * @old_dentry: dentry for file to link to | ||
1711 | * @dir: inode destination for new link | ||
1712 | * @dentry: dentry for link | ||
1713 | * | ||
1714 | */ | ||
1715 | |||
1716 | static int | ||
1717 | v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, | ||
1718 | struct dentry *dentry) | ||
1719 | { | ||
1720 | int err; | ||
1721 | struct p9_fid *dfid, *oldfid; | ||
1722 | char *name; | ||
1723 | struct v9fs_session_info *v9ses; | ||
1724 | struct dentry *dir_dentry; | ||
1725 | |||
1726 | P9_DPRINTK(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n", | ||
1727 | dir->i_ino, old_dentry->d_name.name, | ||
1728 | dentry->d_name.name); | ||
1729 | |||
1730 | v9ses = v9fs_inode2v9ses(dir); | ||
1731 | dir_dentry = v9fs_dentry_from_dir_inode(dir); | ||
1732 | dfid = v9fs_fid_lookup(dir_dentry); | ||
1733 | if (IS_ERR(dfid)) | ||
1734 | return PTR_ERR(dfid); | ||
1735 | |||
1736 | oldfid = v9fs_fid_lookup(old_dentry); | ||
1737 | if (IS_ERR(oldfid)) | ||
1738 | return PTR_ERR(oldfid); | ||
1739 | |||
1740 | name = (char *) dentry->d_name.name; | ||
1741 | |||
1742 | err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name); | ||
1743 | |||
1744 | if (err < 0) { | ||
1745 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_link failed %d\n", err); | ||
1746 | return err; | ||
1747 | } | ||
1748 | |||
1749 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { | ||
1750 | /* Get the latest stat info from server. */ | ||
1751 | struct p9_fid *fid; | ||
1752 | struct p9_stat_dotl *st; | ||
1753 | |||
1754 | fid = v9fs_fid_lookup(old_dentry); | ||
1755 | if (IS_ERR(fid)) | ||
1756 | return PTR_ERR(fid); | ||
1757 | |||
1758 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); | ||
1759 | if (IS_ERR(st)) | ||
1760 | return PTR_ERR(st); | ||
1761 | |||
1762 | v9fs_stat2inode_dotl(st, old_dentry->d_inode); | ||
1763 | |||
1764 | kfree(st); | ||
1765 | } else { | ||
1766 | /* Caching disabled. No need to get upto date stat info. | ||
1767 | * This dentry will be released immediately. So, just i_count++ | ||
1768 | */ | ||
1769 | atomic_inc(&old_dentry->d_inode->i_count); | ||
1770 | } | ||
1771 | |||
1772 | dentry->d_op = old_dentry->d_op; | ||
1773 | d_instantiate(dentry, old_dentry->d_inode); | ||
1774 | |||
1775 | return err; | ||
1776 | } | ||
1777 | |||
1778 | /** | ||
1189 | * v9fs_vfs_mknod - create a special file | 1779 | * v9fs_vfs_mknod - create a special file |
1190 | * @dir: inode destination for new link | 1780 | * @dir: inode destination for new link |
1191 | * @dentry: dentry for file | 1781 | * @dentry: dentry for file |
@@ -1230,6 +1820,100 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) | |||
1230 | return retval; | 1820 | return retval; |
1231 | } | 1821 | } |
1232 | 1822 | ||
1823 | /** | ||
1824 | * v9fs_vfs_mknod_dotl - create a special file | ||
1825 | * @dir: inode destination for new link | ||
1826 | * @dentry: dentry for file | ||
1827 | * @mode: mode for creation | ||
1828 | * @rdev: device associated with special file | ||
1829 | * | ||
1830 | */ | ||
1831 | static int | ||
1832 | v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, | ||
1833 | dev_t rdev) | ||
1834 | { | ||
1835 | int err; | ||
1836 | char *name; | ||
1837 | struct v9fs_session_info *v9ses; | ||
1838 | struct p9_fid *fid = NULL, *dfid = NULL; | ||
1839 | struct inode *inode; | ||
1840 | gid_t gid; | ||
1841 | struct p9_qid qid; | ||
1842 | struct dentry *dir_dentry; | ||
1843 | |||
1844 | P9_DPRINTK(P9_DEBUG_VFS, | ||
1845 | " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, | ||
1846 | dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); | ||
1847 | |||
1848 | if (!new_valid_dev(rdev)) | ||
1849 | return -EINVAL; | ||
1850 | |||
1851 | v9ses = v9fs_inode2v9ses(dir); | ||
1852 | dir_dentry = v9fs_dentry_from_dir_inode(dir); | ||
1853 | dfid = v9fs_fid_lookup(dir_dentry); | ||
1854 | if (IS_ERR(dfid)) { | ||
1855 | err = PTR_ERR(dfid); | ||
1856 | P9_DPRINTK(P9_DEBUG_VFS, "fid lookup failed %d\n", err); | ||
1857 | dfid = NULL; | ||
1858 | goto error; | ||
1859 | } | ||
1860 | |||
1861 | gid = v9fs_get_fsgid_for_create(dir); | ||
1862 | if (gid < 0) { | ||
1863 | P9_DPRINTK(P9_DEBUG_VFS, "v9fs_get_fsgid_for_create failed\n"); | ||
1864 | goto error; | ||
1865 | } | ||
1866 | |||
1867 | name = (char *) dentry->d_name.name; | ||
1868 | |||
1869 | err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); | ||
1870 | if (err < 0) | ||
1871 | goto error; | ||
1872 | |||
1873 | /* instantiate inode and assign the unopened fid to the dentry */ | ||
1874 | if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { | ||
1875 | fid = p9_client_walk(dfid, 1, &name, 1); | ||
1876 | if (IS_ERR(fid)) { | ||
1877 | err = PTR_ERR(fid); | ||
1878 | P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", | ||
1879 | err); | ||
1880 | fid = NULL; | ||
1881 | goto error; | ||
1882 | } | ||
1883 | |||
1884 | inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb); | ||
1885 | if (IS_ERR(inode)) { | ||
1886 | err = PTR_ERR(inode); | ||
1887 | P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", | ||
1888 | err); | ||
1889 | goto error; | ||
1890 | } | ||
1891 | dentry->d_op = &v9fs_cached_dentry_operations; | ||
1892 | d_instantiate(dentry, inode); | ||
1893 | err = v9fs_fid_add(dentry, fid); | ||
1894 | if (err < 0) | ||
1895 | goto error; | ||
1896 | fid = NULL; | ||
1897 | } else { | ||
1898 | /* | ||
1899 | * Not in cached mode. No need to populate inode with stat. | ||
1900 | * socket syscall returns a fd, so we need instantiate | ||
1901 | */ | ||
1902 | inode = v9fs_get_inode(dir->i_sb, mode); | ||
1903 | if (IS_ERR(inode)) { | ||
1904 | err = PTR_ERR(inode); | ||
1905 | goto error; | ||
1906 | } | ||
1907 | dentry->d_op = &v9fs_dentry_operations; | ||
1908 | d_instantiate(dentry, inode); | ||
1909 | } | ||
1910 | |||
1911 | error: | ||
1912 | if (fid) | ||
1913 | p9_client_clunk(fid); | ||
1914 | return err; | ||
1915 | } | ||
1916 | |||
1233 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { | 1917 | static const struct inode_operations v9fs_dir_inode_operations_dotu = { |
1234 | .create = v9fs_vfs_create, | 1918 | .create = v9fs_vfs_create, |
1235 | .lookup = v9fs_vfs_lookup, | 1919 | .lookup = v9fs_vfs_lookup, |
@@ -1238,24 +1922,29 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = { | |||
1238 | .unlink = v9fs_vfs_unlink, | 1922 | .unlink = v9fs_vfs_unlink, |
1239 | .mkdir = v9fs_vfs_mkdir, | 1923 | .mkdir = v9fs_vfs_mkdir, |
1240 | .rmdir = v9fs_vfs_rmdir, | 1924 | .rmdir = v9fs_vfs_rmdir, |
1241 | .mknod = v9fs_vfs_mknod, | 1925 | .mknod = v9fs_vfs_mknod_dotl, |
1242 | .rename = v9fs_vfs_rename, | 1926 | .rename = v9fs_vfs_rename, |
1243 | .getattr = v9fs_vfs_getattr, | 1927 | .getattr = v9fs_vfs_getattr, |
1244 | .setattr = v9fs_vfs_setattr, | 1928 | .setattr = v9fs_vfs_setattr, |
1245 | }; | 1929 | }; |
1246 | 1930 | ||
1247 | static const struct inode_operations v9fs_dir_inode_operations_dotl = { | 1931 | static const struct inode_operations v9fs_dir_inode_operations_dotl = { |
1248 | .create = v9fs_vfs_create, | 1932 | .create = v9fs_vfs_create_dotl, |
1249 | .lookup = v9fs_vfs_lookup, | 1933 | .lookup = v9fs_vfs_lookup, |
1250 | .symlink = v9fs_vfs_symlink, | 1934 | .link = v9fs_vfs_link_dotl, |
1251 | .link = v9fs_vfs_link, | 1935 | .symlink = v9fs_vfs_symlink_dotl, |
1252 | .unlink = v9fs_vfs_unlink, | 1936 | .unlink = v9fs_vfs_unlink, |
1253 | .mkdir = v9fs_vfs_mkdir, | 1937 | .mkdir = v9fs_vfs_mkdir_dotl, |
1254 | .rmdir = v9fs_vfs_rmdir, | 1938 | .rmdir = v9fs_vfs_rmdir, |
1255 | .mknod = v9fs_vfs_mknod, | 1939 | .mknod = v9fs_vfs_mknod_dotl, |
1256 | .rename = v9fs_vfs_rename, | 1940 | .rename = v9fs_vfs_rename, |
1257 | .getattr = v9fs_vfs_getattr, | 1941 | .getattr = v9fs_vfs_getattr_dotl, |
1258 | .setattr = v9fs_vfs_setattr, | 1942 | .setattr = v9fs_vfs_setattr_dotl, |
1943 | .setxattr = generic_setxattr, | ||
1944 | .getxattr = generic_getxattr, | ||
1945 | .removexattr = generic_removexattr, | ||
1946 | .listxattr = v9fs_listxattr, | ||
1947 | |||
1259 | }; | 1948 | }; |
1260 | 1949 | ||
1261 | static const struct inode_operations v9fs_dir_inode_operations = { | 1950 | static const struct inode_operations v9fs_dir_inode_operations = { |
@@ -1276,8 +1965,12 @@ static const struct inode_operations v9fs_file_inode_operations = { | |||
1276 | }; | 1965 | }; |
1277 | 1966 | ||
1278 | static const struct inode_operations v9fs_file_inode_operations_dotl = { | 1967 | static const struct inode_operations v9fs_file_inode_operations_dotl = { |
1279 | .getattr = v9fs_vfs_getattr, | 1968 | .getattr = v9fs_vfs_getattr_dotl, |
1280 | .setattr = v9fs_vfs_setattr, | 1969 | .setattr = v9fs_vfs_setattr_dotl, |
1970 | .setxattr = generic_setxattr, | ||
1971 | .getxattr = generic_getxattr, | ||
1972 | .removexattr = generic_removexattr, | ||
1973 | .listxattr = v9fs_listxattr, | ||
1281 | }; | 1974 | }; |
1282 | 1975 | ||
1283 | static const struct inode_operations v9fs_symlink_inode_operations = { | 1976 | static const struct inode_operations v9fs_symlink_inode_operations = { |
@@ -1292,6 +1985,10 @@ static const struct inode_operations v9fs_symlink_inode_operations_dotl = { | |||
1292 | .readlink = generic_readlink, | 1985 | .readlink = generic_readlink, |
1293 | .follow_link = v9fs_vfs_follow_link, | 1986 | .follow_link = v9fs_vfs_follow_link, |
1294 | .put_link = v9fs_vfs_put_link, | 1987 | .put_link = v9fs_vfs_put_link, |
1295 | .getattr = v9fs_vfs_getattr, | 1988 | .getattr = v9fs_vfs_getattr_dotl, |
1296 | .setattr = v9fs_vfs_setattr, | 1989 | .setattr = v9fs_vfs_setattr_dotl, |
1990 | .setxattr = generic_setxattr, | ||
1991 | .getxattr = generic_getxattr, | ||
1992 | .removexattr = generic_removexattr, | ||
1993 | .listxattr = v9fs_listxattr, | ||
1297 | }; | 1994 | }; |
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index be74d020436e..4b9ede0b41b7 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include "v9fs.h" | 45 | #include "v9fs.h" |
46 | #include "v9fs_vfs.h" | 46 | #include "v9fs_vfs.h" |
47 | #include "fid.h" | 47 | #include "fid.h" |
48 | #include "xattr.h" | ||
48 | 49 | ||
49 | static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; | 50 | static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; |
50 | 51 | ||
@@ -77,9 +78,10 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, | |||
77 | sb->s_blocksize_bits = fls(v9ses->maxdata - 1); | 78 | sb->s_blocksize_bits = fls(v9ses->maxdata - 1); |
78 | sb->s_blocksize = 1 << sb->s_blocksize_bits; | 79 | sb->s_blocksize = 1 << sb->s_blocksize_bits; |
79 | sb->s_magic = V9FS_MAGIC; | 80 | sb->s_magic = V9FS_MAGIC; |
80 | if (v9fs_proto_dotl(v9ses)) | 81 | if (v9fs_proto_dotl(v9ses)) { |
81 | sb->s_op = &v9fs_super_ops_dotl; | 82 | sb->s_op = &v9fs_super_ops_dotl; |
82 | else | 83 | sb->s_xattr = v9fs_xattr_handlers; |
84 | } else | ||
83 | sb->s_op = &v9fs_super_ops; | 85 | sb->s_op = &v9fs_super_ops; |
84 | sb->s_bdi = &v9ses->bdi; | 86 | sb->s_bdi = &v9ses->bdi; |
85 | 87 | ||
@@ -107,7 +109,6 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
107 | struct inode *inode = NULL; | 109 | struct inode *inode = NULL; |
108 | struct dentry *root = NULL; | 110 | struct dentry *root = NULL; |
109 | struct v9fs_session_info *v9ses = NULL; | 111 | struct v9fs_session_info *v9ses = NULL; |
110 | struct p9_wstat *st = NULL; | ||
111 | int mode = S_IRWXUGO | S_ISVTX; | 112 | int mode = S_IRWXUGO | S_ISVTX; |
112 | struct p9_fid *fid; | 113 | struct p9_fid *fid; |
113 | int retval = 0; | 114 | int retval = 0; |
@@ -124,16 +125,10 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
124 | goto close_session; | 125 | goto close_session; |
125 | } | 126 | } |
126 | 127 | ||
127 | st = p9_client_stat(fid); | ||
128 | if (IS_ERR(st)) { | ||
129 | retval = PTR_ERR(st); | ||
130 | goto clunk_fid; | ||
131 | } | ||
132 | |||
133 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); | 128 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); |
134 | if (IS_ERR(sb)) { | 129 | if (IS_ERR(sb)) { |
135 | retval = PTR_ERR(sb); | 130 | retval = PTR_ERR(sb); |
136 | goto free_stat; | 131 | goto clunk_fid; |
137 | } | 132 | } |
138 | v9fs_fill_super(sb, v9ses, flags, data); | 133 | v9fs_fill_super(sb, v9ses, flags, data); |
139 | 134 | ||
@@ -151,22 +146,38 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, | |||
151 | } | 146 | } |
152 | 147 | ||
153 | sb->s_root = root; | 148 | sb->s_root = root; |
154 | root->d_inode->i_ino = v9fs_qid2ino(&st->qid); | ||
155 | 149 | ||
156 | v9fs_stat2inode(st, root->d_inode, sb); | 150 | if (v9fs_proto_dotl(v9ses)) { |
151 | struct p9_stat_dotl *st = NULL; | ||
152 | st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); | ||
153 | if (IS_ERR(st)) { | ||
154 | retval = PTR_ERR(st); | ||
155 | goto clunk_fid; | ||
156 | } | ||
157 | |||
158 | v9fs_stat2inode_dotl(st, root->d_inode); | ||
159 | kfree(st); | ||
160 | } else { | ||
161 | struct p9_wstat *st = NULL; | ||
162 | st = p9_client_stat(fid); | ||
163 | if (IS_ERR(st)) { | ||
164 | retval = PTR_ERR(st); | ||
165 | goto clunk_fid; | ||
166 | } | ||
167 | |||
168 | root->d_inode->i_ino = v9fs_qid2ino(&st->qid); | ||
169 | v9fs_stat2inode(st, root->d_inode, sb); | ||
170 | |||
171 | p9stat_free(st); | ||
172 | kfree(st); | ||
173 | } | ||
157 | 174 | ||
158 | v9fs_fid_add(root, fid); | 175 | v9fs_fid_add(root, fid); |
159 | p9stat_free(st); | ||
160 | kfree(st); | ||
161 | 176 | ||
162 | P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); | 177 | P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n"); |
163 | simple_set_mnt(mnt, sb); | 178 | simple_set_mnt(mnt, sb); |
164 | return 0; | 179 | return 0; |
165 | 180 | ||
166 | free_stat: | ||
167 | p9stat_free(st); | ||
168 | kfree(st); | ||
169 | |||
170 | clunk_fid: | 181 | clunk_fid: |
171 | p9_client_clunk(fid); | 182 | p9_client_clunk(fid); |
172 | 183 | ||
@@ -176,8 +187,6 @@ close_session: | |||
176 | return retval; | 187 | return retval; |
177 | 188 | ||
178 | release_sb: | 189 | release_sb: |
179 | p9stat_free(st); | ||
180 | kfree(st); | ||
181 | deactivate_locked_super(sb); | 190 | deactivate_locked_super(sb); |
182 | return retval; | 191 | return retval; |
183 | } | 192 | } |
@@ -278,4 +287,5 @@ struct file_system_type v9fs_fs_type = { | |||
278 | .get_sb = v9fs_get_sb, | 287 | .get_sb = v9fs_get_sb, |
279 | .kill_sb = v9fs_kill_super, | 288 | .kill_sb = v9fs_kill_super, |
280 | .owner = THIS_MODULE, | 289 | .owner = THIS_MODULE, |
290 | .fs_flags = FS_RENAME_DOES_D_MOVE, | ||
281 | }; | 291 | }; |
diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c new file mode 100644 index 000000000000..f88e5c2dc873 --- /dev/null +++ b/fs/9p/xattr.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corporation, 2010 | ||
3 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2.1 of the GNU Lesser General Public License | ||
7 | * as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/fs.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <net/9p/9p.h> | ||
19 | #include <net/9p/client.h> | ||
20 | |||
21 | #include "fid.h" | ||
22 | #include "xattr.h" | ||
23 | |||
24 | /* | ||
25 | * v9fs_xattr_get() | ||
26 | * | ||
27 | * Copy an extended attribute into the buffer | ||
28 | * provided, or compute the buffer size required. | ||
29 | * Buffer is NULL to compute the size of the buffer required. | ||
30 | * | ||
31 | * Returns a negative error number on failure, or the number of bytes | ||
32 | * used / required on success. | ||
33 | */ | ||
34 | ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name, | ||
35 | void *buffer, size_t buffer_size) | ||
36 | { | ||
37 | ssize_t retval; | ||
38 | int msize, read_count; | ||
39 | u64 offset = 0, attr_size; | ||
40 | struct p9_fid *fid, *attr_fid; | ||
41 | |||
42 | P9_DPRINTK(P9_DEBUG_VFS, "%s: name = %s value_len = %zu\n", | ||
43 | __func__, name, buffer_size); | ||
44 | |||
45 | fid = v9fs_fid_lookup(dentry); | ||
46 | if (IS_ERR(fid)) | ||
47 | return PTR_ERR(fid); | ||
48 | |||
49 | attr_fid = p9_client_xattrwalk(fid, name, &attr_size); | ||
50 | if (IS_ERR(attr_fid)) { | ||
51 | retval = PTR_ERR(attr_fid); | ||
52 | P9_DPRINTK(P9_DEBUG_VFS, | ||
53 | "p9_client_attrwalk failed %zd\n", retval); | ||
54 | attr_fid = NULL; | ||
55 | goto error; | ||
56 | } | ||
57 | if (!buffer_size) { | ||
58 | /* request to get the attr_size */ | ||
59 | retval = attr_size; | ||
60 | goto error; | ||
61 | } | ||
62 | if (attr_size > buffer_size) { | ||
63 | retval = -ERANGE; | ||
64 | goto error; | ||
65 | } | ||
66 | msize = attr_fid->clnt->msize; | ||
67 | while (attr_size) { | ||
68 | if (attr_size > (msize - P9_IOHDRSZ)) | ||
69 | read_count = msize - P9_IOHDRSZ; | ||
70 | else | ||
71 | read_count = attr_size; | ||
72 | read_count = p9_client_read(attr_fid, ((char *)buffer)+offset, | ||
73 | NULL, offset, read_count); | ||
74 | if (read_count < 0) { | ||
75 | /* error in xattr read */ | ||
76 | retval = read_count; | ||
77 | goto error; | ||
78 | } | ||
79 | offset += read_count; | ||
80 | attr_size -= read_count; | ||
81 | } | ||
82 | /* Total read xattr bytes */ | ||
83 | retval = offset; | ||
84 | error: | ||
85 | if (attr_fid) | ||
86 | p9_client_clunk(attr_fid); | ||
87 | return retval; | ||
88 | |||
89 | } | ||
90 | |||
91 | /* | ||
92 | * v9fs_xattr_set() | ||
93 | * | ||
94 | * Create, replace or remove an extended attribute for this inode. Buffer | ||
95 | * is NULL to remove an existing extended attribute, and non-NULL to | ||
96 | * either replace an existing extended attribute, or create a new extended | ||
97 | * attribute. The flags XATTR_REPLACE and XATTR_CREATE | ||
98 | * specify that an extended attribute must exist and must not exist | ||
99 | * previous to the call, respectively. | ||
100 | * | ||
101 | * Returns 0, or a negative error number on failure. | ||
102 | */ | ||
103 | int v9fs_xattr_set(struct dentry *dentry, const char *name, | ||
104 | const void *value, size_t value_len, int flags) | ||
105 | { | ||
106 | u64 offset = 0; | ||
107 | int retval, msize, write_count; | ||
108 | struct p9_fid *fid = NULL; | ||
109 | |||
110 | P9_DPRINTK(P9_DEBUG_VFS, "%s: name = %s value_len = %zu flags = %d\n", | ||
111 | __func__, name, value_len, flags); | ||
112 | |||
113 | fid = v9fs_fid_clone(dentry); | ||
114 | if (IS_ERR(fid)) { | ||
115 | retval = PTR_ERR(fid); | ||
116 | fid = NULL; | ||
117 | goto error; | ||
118 | } | ||
119 | /* | ||
120 | * On success fid points to xattr | ||
121 | */ | ||
122 | retval = p9_client_xattrcreate(fid, name, value_len, flags); | ||
123 | if (retval < 0) { | ||
124 | P9_DPRINTK(P9_DEBUG_VFS, | ||
125 | "p9_client_xattrcreate failed %d\n", retval); | ||
126 | goto error; | ||
127 | } | ||
128 | msize = fid->clnt->msize;; | ||
129 | while (value_len) { | ||
130 | if (value_len > (msize - P9_IOHDRSZ)) | ||
131 | write_count = msize - P9_IOHDRSZ; | ||
132 | else | ||
133 | write_count = value_len; | ||
134 | write_count = p9_client_write(fid, ((char *)value)+offset, | ||
135 | NULL, offset, write_count); | ||
136 | if (write_count < 0) { | ||
137 | /* error in xattr write */ | ||
138 | retval = write_count; | ||
139 | goto error; | ||
140 | } | ||
141 | offset += write_count; | ||
142 | value_len -= write_count; | ||
143 | } | ||
144 | /* Total read xattr bytes */ | ||
145 | retval = offset; | ||
146 | error: | ||
147 | if (fid) | ||
148 | retval = p9_client_clunk(fid); | ||
149 | return retval; | ||
150 | } | ||
151 | |||
152 | ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) | ||
153 | { | ||
154 | return v9fs_xattr_get(dentry, NULL, buffer, buffer_size); | ||
155 | } | ||
156 | |||
157 | const struct xattr_handler *v9fs_xattr_handlers[] = { | ||
158 | &v9fs_xattr_user_handler, | ||
159 | NULL | ||
160 | }; | ||
diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h new file mode 100644 index 000000000000..9ddf672ae5c4 --- /dev/null +++ b/fs/9p/xattr.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corporation, 2010 | ||
3 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2.1 of the GNU Lesser General Public License | ||
7 | * as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | * | ||
13 | */ | ||
14 | #ifndef FS_9P_XATTR_H | ||
15 | #define FS_9P_XATTR_H | ||
16 | |||
17 | #include <linux/xattr.h> | ||
18 | |||
19 | extern const struct xattr_handler *v9fs_xattr_handlers[]; | ||
20 | extern struct xattr_handler v9fs_xattr_user_handler; | ||
21 | |||
22 | extern ssize_t v9fs_xattr_get(struct dentry *, const char *, | ||
23 | void *, size_t); | ||
24 | extern int v9fs_xattr_set(struct dentry *, const char *, | ||
25 | const void *, size_t, int); | ||
26 | extern ssize_t v9fs_listxattr(struct dentry *, char *, size_t); | ||
27 | #endif /* FS_9P_XATTR_H */ | ||
diff --git a/fs/9p/xattr_user.c b/fs/9p/xattr_user.c new file mode 100644 index 000000000000..d0b701b72080 --- /dev/null +++ b/fs/9p/xattr_user.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corporation, 2010 | ||
3 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2.1 of the GNU Lesser General Public License | ||
7 | * as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include "xattr.h" | ||
21 | |||
22 | static int v9fs_xattr_user_get(struct dentry *dentry, const char *name, | ||
23 | void *buffer, size_t size, int type) | ||
24 | { | ||
25 | int retval; | ||
26 | char *full_name; | ||
27 | size_t name_len; | ||
28 | size_t prefix_len = XATTR_USER_PREFIX_LEN; | ||
29 | |||
30 | if (name == NULL) | ||
31 | return -EINVAL; | ||
32 | |||
33 | if (strcmp(name, "") == 0) | ||
34 | return -EINVAL; | ||
35 | |||
36 | name_len = strlen(name); | ||
37 | full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); | ||
38 | if (!full_name) | ||
39 | return -ENOMEM; | ||
40 | memcpy(full_name, XATTR_USER_PREFIX, prefix_len); | ||
41 | memcpy(full_name+prefix_len, name, name_len); | ||
42 | full_name[prefix_len + name_len] = '\0'; | ||
43 | |||
44 | retval = v9fs_xattr_get(dentry, full_name, buffer, size); | ||
45 | kfree(full_name); | ||
46 | return retval; | ||
47 | } | ||
48 | |||
49 | static int v9fs_xattr_user_set(struct dentry *dentry, const char *name, | ||
50 | const void *value, size_t size, int flags, int type) | ||
51 | { | ||
52 | int retval; | ||
53 | char *full_name; | ||
54 | size_t name_len; | ||
55 | size_t prefix_len = XATTR_USER_PREFIX_LEN; | ||
56 | |||
57 | if (name == NULL) | ||
58 | return -EINVAL; | ||
59 | |||
60 | if (strcmp(name, "") == 0) | ||
61 | return -EINVAL; | ||
62 | |||
63 | name_len = strlen(name); | ||
64 | full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); | ||
65 | if (!full_name) | ||
66 | return -ENOMEM; | ||
67 | memcpy(full_name, XATTR_USER_PREFIX, prefix_len); | ||
68 | memcpy(full_name + prefix_len, name, name_len); | ||
69 | full_name[prefix_len + name_len] = '\0'; | ||
70 | |||
71 | retval = v9fs_xattr_set(dentry, full_name, value, size, flags); | ||
72 | kfree(full_name); | ||
73 | return retval; | ||
74 | } | ||
75 | |||
76 | struct xattr_handler v9fs_xattr_user_handler = { | ||
77 | .prefix = XATTR_USER_PREFIX, | ||
78 | .get = v9fs_xattr_user_get, | ||
79 | .set = v9fs_xattr_user_set, | ||
80 | }; | ||
diff --git a/fs/Kconfig b/fs/Kconfig index 5f85b5947613..3d185308ec88 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -64,7 +64,7 @@ source "fs/autofs4/Kconfig" | |||
64 | source "fs/fuse/Kconfig" | 64 | source "fs/fuse/Kconfig" |
65 | 65 | ||
66 | config CUSE | 66 | config CUSE |
67 | tristate "Character device in Userpace support" | 67 | tristate "Character device in Userspace support" |
68 | depends on FUSE_FS | 68 | depends on FUSE_FS |
69 | help | 69 | help |
70 | This FUSE extension allows character devices to be | 70 | This FUSE extension allows character devices to be |
diff --git a/fs/afs/Kconfig b/fs/afs/Kconfig index 5c4e61d3c772..8f975f25b486 100644 --- a/fs/afs/Kconfig +++ b/fs/afs/Kconfig | |||
@@ -2,6 +2,7 @@ config AFS_FS | |||
2 | tristate "Andrew File System support (AFS) (EXPERIMENTAL)" | 2 | tristate "Andrew File System support (AFS) (EXPERIMENTAL)" |
3 | depends on INET && EXPERIMENTAL | 3 | depends on INET && EXPERIMENTAL |
4 | select AF_RXRPC | 4 | select AF_RXRPC |
5 | select DNS_RESOLVER | ||
5 | help | 6 | help |
6 | If you say Y here, you will get an experimental Andrew File System | 7 | If you say Y here, you will get an experimental Andrew File System |
7 | driver. It currently only supports unsecured read-only AFS access. | 8 | driver. It currently only supports unsecured read-only AFS access. |
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index e19c13f059ed..ffea35c63879 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/key.h> | 14 | #include <linux/key.h> |
15 | #include <linux/ctype.h> | 15 | #include <linux/ctype.h> |
16 | #include <linux/dns_resolver.h> | ||
16 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
17 | #include <keys/rxrpc-type.h> | 18 | #include <keys/rxrpc-type.h> |
18 | #include "internal.h" | 19 | #include "internal.h" |
@@ -36,6 +37,8 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist) | |||
36 | struct key *key; | 37 | struct key *key; |
37 | size_t namelen; | 38 | size_t namelen; |
38 | char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next; | 39 | char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next; |
40 | char *dvllist = NULL, *_vllist = NULL; | ||
41 | char delimiter = ':'; | ||
39 | int ret; | 42 | int ret; |
40 | 43 | ||
41 | _enter("%s,%s", name, vllist); | 44 | _enter("%s,%s", name, vllist); |
@@ -43,8 +46,10 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist) | |||
43 | BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ | 46 | BUG_ON(!name); /* TODO: want to look up "this cell" in the cache */ |
44 | 47 | ||
45 | namelen = strlen(name); | 48 | namelen = strlen(name); |
46 | if (namelen > AFS_MAXCELLNAME) | 49 | if (namelen > AFS_MAXCELLNAME) { |
50 | _leave(" = -ENAMETOOLONG"); | ||
47 | return ERR_PTR(-ENAMETOOLONG); | 51 | return ERR_PTR(-ENAMETOOLONG); |
52 | } | ||
48 | 53 | ||
49 | /* allocate and initialise a cell record */ | 54 | /* allocate and initialise a cell record */ |
50 | cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL); | 55 | cell = kzalloc(sizeof(struct afs_cell) + namelen + 1, GFP_KERNEL); |
@@ -64,15 +69,31 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist) | |||
64 | INIT_LIST_HEAD(&cell->vl_list); | 69 | INIT_LIST_HEAD(&cell->vl_list); |
65 | spin_lock_init(&cell->vl_lock); | 70 | spin_lock_init(&cell->vl_lock); |
66 | 71 | ||
72 | /* if the ip address is invalid, try dns query */ | ||
73 | if (!vllist || strlen(vllist) < 7) { | ||
74 | ret = dns_query("afsdb", name, namelen, "ipv4", &dvllist, NULL); | ||
75 | if (ret < 0) { | ||
76 | _leave(" = %d", ret); | ||
77 | return ERR_PTR(ret); | ||
78 | } | ||
79 | _vllist = dvllist; | ||
80 | |||
81 | /* change the delimiter for user-space reply */ | ||
82 | delimiter = ','; | ||
83 | |||
84 | } else { | ||
85 | _vllist = vllist; | ||
86 | } | ||
87 | |||
67 | /* fill in the VL server list from the rest of the string */ | 88 | /* fill in the VL server list from the rest of the string */ |
68 | do { | 89 | do { |
69 | unsigned a, b, c, d; | 90 | unsigned a, b, c, d; |
70 | 91 | ||
71 | next = strchr(vllist, ':'); | 92 | next = strchr(_vllist, delimiter); |
72 | if (next) | 93 | if (next) |
73 | *next++ = 0; | 94 | *next++ = 0; |
74 | 95 | ||
75 | if (sscanf(vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) | 96 | if (sscanf(_vllist, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) |
76 | goto bad_address; | 97 | goto bad_address; |
77 | 98 | ||
78 | if (a > 255 || b > 255 || c > 255 || d > 255) | 99 | if (a > 255 || b > 255 || c > 255 || d > 255) |
@@ -81,7 +102,7 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist) | |||
81 | cell->vl_addrs[cell->vl_naddrs++].s_addr = | 102 | cell->vl_addrs[cell->vl_naddrs++].s_addr = |
82 | htonl((a << 24) | (b << 16) | (c << 8) | d); | 103 | htonl((a << 24) | (b << 16) | (c << 8) | d); |
83 | 104 | ||
84 | } while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (vllist = next)); | 105 | } while (cell->vl_naddrs < AFS_CELL_MAX_ADDRS && (_vllist = next)); |
85 | 106 | ||
86 | /* create a key to represent an anonymous user */ | 107 | /* create a key to represent an anonymous user */ |
87 | memcpy(keyname, "afs@", 4); | 108 | memcpy(keyname, "afs@", 4); |
@@ -110,6 +131,7 @@ bad_address: | |||
110 | ret = -EINVAL; | 131 | ret = -EINVAL; |
111 | error: | 132 | error: |
112 | key_put(cell->anonymous_key); | 133 | key_put(cell->anonymous_key); |
134 | kfree(dvllist); | ||
113 | kfree(cell); | 135 | kfree(cell); |
114 | _leave(" = %d", ret); | 136 | _leave(" = %d", ret); |
115 | return ERR_PTR(ret); | 137 | return ERR_PTR(ret); |
@@ -201,14 +223,12 @@ int afs_cell_init(char *rootcell) | |||
201 | } | 223 | } |
202 | 224 | ||
203 | cp = strchr(rootcell, ':'); | 225 | cp = strchr(rootcell, ':'); |
204 | if (!cp) { | 226 | if (!cp) |
205 | printk(KERN_ERR "kAFS: no VL server IP addresses specified\n"); | 227 | _debug("kAFS: no VL server IP addresses specified"); |
206 | _leave(" = -EINVAL"); | 228 | else |
207 | return -EINVAL; | 229 | *cp++ = 0; |
208 | } | ||
209 | 230 | ||
210 | /* allocate a cell record for the root cell */ | 231 | /* allocate a cell record for the root cell */ |
211 | *cp++ = 0; | ||
212 | new_root = afs_cell_create(rootcell, cp); | 232 | new_root = afs_cell_create(rootcell, cp); |
213 | if (IS_ERR(new_root)) { | 233 | if (IS_ERR(new_root)) { |
214 | _leave(" = %ld", PTR_ERR(new_root)); | 234 | _leave(" = %ld", PTR_ERR(new_root)); |
diff --git a/fs/afs/main.c b/fs/afs/main.c index 66d54d348c55..cfd1cbe25b22 100644 --- a/fs/afs/main.c +++ b/fs/afs/main.c | |||
@@ -111,6 +111,8 @@ static int __init afs_init(void) | |||
111 | 111 | ||
112 | /* initialise the callback update process */ | 112 | /* initialise the callback update process */ |
113 | ret = afs_callback_update_init(); | 113 | ret = afs_callback_update_init(); |
114 | if (ret < 0) | ||
115 | goto error_callback_update_init; | ||
114 | 116 | ||
115 | /* create the RxRPC transport */ | 117 | /* create the RxRPC transport */ |
116 | ret = afs_open_socket(); | 118 | ret = afs_open_socket(); |
@@ -127,15 +129,16 @@ static int __init afs_init(void) | |||
127 | error_fs: | 129 | error_fs: |
128 | afs_close_socket(); | 130 | afs_close_socket(); |
129 | error_open_socket: | 131 | error_open_socket: |
132 | afs_callback_update_kill(); | ||
133 | error_callback_update_init: | ||
134 | afs_vlocation_purge(); | ||
130 | error_vl_update_init: | 135 | error_vl_update_init: |
136 | afs_cell_purge(); | ||
131 | error_cell_init: | 137 | error_cell_init: |
132 | #ifdef CONFIG_AFS_FSCACHE | 138 | #ifdef CONFIG_AFS_FSCACHE |
133 | fscache_unregister_netfs(&afs_cache_netfs); | 139 | fscache_unregister_netfs(&afs_cache_netfs); |
134 | error_cache: | 140 | error_cache: |
135 | #endif | 141 | #endif |
136 | afs_callback_update_kill(); | ||
137 | afs_vlocation_purge(); | ||
138 | afs_cell_purge(); | ||
139 | afs_proc_cleanup(); | 142 | afs_proc_cleanup(); |
140 | rcu_barrier(); | 143 | rcu_barrier(); |
141 | printk(KERN_ERR "kAFS: failed to register: %d\n", ret); | 144 | printk(KERN_ERR "kAFS: failed to register: %d\n", ret); |
diff --git a/fs/afs/write.c b/fs/afs/write.c index 3dab9e9948d0..722743b152d8 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c | |||
@@ -680,7 +680,6 @@ int afs_writeback_all(struct afs_vnode *vnode) | |||
680 | { | 680 | { |
681 | struct address_space *mapping = vnode->vfs_inode.i_mapping; | 681 | struct address_space *mapping = vnode->vfs_inode.i_mapping; |
682 | struct writeback_control wbc = { | 682 | struct writeback_control wbc = { |
683 | .bdi = mapping->backing_dev_info, | ||
684 | .sync_mode = WB_SYNC_ALL, | 683 | .sync_mode = WB_SYNC_ALL, |
685 | .nr_to_write = LONG_MAX, | 684 | .nr_to_write = LONG_MAX, |
686 | .range_cyclic = 1, | 685 | .range_cyclic = 1, |
@@ -1277,7 +1277,7 @@ out: | |||
1277 | /* sys_io_destroy: | 1277 | /* sys_io_destroy: |
1278 | * Destroy the aio_context specified. May cancel any outstanding | 1278 | * Destroy the aio_context specified. May cancel any outstanding |
1279 | * AIOs and block on completion. Will fail with -ENOSYS if not | 1279 | * AIOs and block on completion. Will fail with -ENOSYS if not |
1280 | * implemented. May fail with -EFAULT if the context pointed to | 1280 | * implemented. May fail with -EINVAL if the context pointed to |
1281 | * is invalid. | 1281 | * is invalid. |
1282 | */ | 1282 | */ |
1283 | SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx) | 1283 | SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx) |
@@ -1795,15 +1795,16 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, | |||
1795 | 1795 | ||
1796 | /* io_getevents: | 1796 | /* io_getevents: |
1797 | * Attempts to read at least min_nr events and up to nr events from | 1797 | * Attempts to read at least min_nr events and up to nr events from |
1798 | * the completion queue for the aio_context specified by ctx_id. May | 1798 | * the completion queue for the aio_context specified by ctx_id. If |
1799 | * fail with -EINVAL if ctx_id is invalid, if min_nr is out of range, | 1799 | * it succeeds, the number of read events is returned. May fail with |
1800 | * if nr is out of range, if when is out of range. May fail with | 1800 | * -EINVAL if ctx_id is invalid, if min_nr is out of range, if nr is |
1801 | * -EFAULT if any of the memory specified to is invalid. May return | 1801 | * out of range, if timeout is out of range. May fail with -EFAULT |
1802 | * 0 or < min_nr if no events are available and the timeout specified | 1802 | * if any of the memory specified is invalid. May return 0 or |
1803 | * by when has elapsed, where when == NULL specifies an infinite | 1803 | * < min_nr if the timeout specified by timeout has elapsed |
1804 | * timeout. Note that the timeout pointed to by when is relative and | 1804 | * before sufficient events are available, where timeout == NULL |
1805 | * will be updated if not NULL and the operation blocks. Will fail | 1805 | * specifies an infinite timeout. Note that the timeout pointed to by |
1806 | * with -ENOSYS if not implemented. | 1806 | * timeout is relative and will be updated if not NULL and the |
1807 | * operation blocks. Will fail with -ENOSYS if not implemented. | ||
1807 | */ | 1808 | */ |
1808 | SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id, | 1809 | SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id, |
1809 | long, min_nr, | 1810 | long, min_nr, |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 34ddda888e63..dc39d2824885 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
@@ -436,7 +436,7 @@ befs_init_inodecache(void) | |||
436 | init_once); | 436 | init_once); |
437 | if (befs_inode_cachep == NULL) { | 437 | if (befs_inode_cachep == NULL) { |
438 | printk(KERN_ERR "befs_init_inodecache: " | 438 | printk(KERN_ERR "befs_init_inodecache: " |
439 | "Couldn't initalize inode slabcache\n"); | 439 | "Couldn't initialize inode slabcache\n"); |
440 | return -ENOMEM; | 440 | return -ENOMEM; |
441 | } | 441 | } |
442 | 442 | ||
diff --git a/fs/block_dev.c b/fs/block_dev.c index 99d6af811747..b3171fb0dc9a 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -681,8 +681,8 @@ retry: | |||
681 | if (!bd_may_claim(bdev, whole, holder)) | 681 | if (!bd_may_claim(bdev, whole, holder)) |
682 | return -EBUSY; | 682 | return -EBUSY; |
683 | 683 | ||
684 | /* if someone else is claiming, wait for it to finish */ | 684 | /* if claiming is already in progress, wait for it to finish */ |
685 | if (whole->bd_claiming && whole->bd_claiming != holder) { | 685 | if (whole->bd_claiming) { |
686 | wait_queue_head_t *wq = bit_waitqueue(&whole->bd_claiming, 0); | 686 | wait_queue_head_t *wq = bit_waitqueue(&whole->bd_claiming, 0); |
687 | DEFINE_WAIT(wait); | 687 | DEFINE_WAIT(wait); |
688 | 688 | ||
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 0d1d966b0fe4..c3df14ce2cc2 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -2304,12 +2304,17 @@ noinline int btrfs_leaf_free_space(struct btrfs_root *root, | |||
2304 | return ret; | 2304 | return ret; |
2305 | } | 2305 | } |
2306 | 2306 | ||
2307 | /* | ||
2308 | * min slot controls the lowest index we're willing to push to the | ||
2309 | * right. We'll push up to and including min_slot, but no lower | ||
2310 | */ | ||
2307 | static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, | 2311 | static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, |
2308 | struct btrfs_root *root, | 2312 | struct btrfs_root *root, |
2309 | struct btrfs_path *path, | 2313 | struct btrfs_path *path, |
2310 | int data_size, int empty, | 2314 | int data_size, int empty, |
2311 | struct extent_buffer *right, | 2315 | struct extent_buffer *right, |
2312 | int free_space, u32 left_nritems) | 2316 | int free_space, u32 left_nritems, |
2317 | u32 min_slot) | ||
2313 | { | 2318 | { |
2314 | struct extent_buffer *left = path->nodes[0]; | 2319 | struct extent_buffer *left = path->nodes[0]; |
2315 | struct extent_buffer *upper = path->nodes[1]; | 2320 | struct extent_buffer *upper = path->nodes[1]; |
@@ -2327,7 +2332,7 @@ static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, | |||
2327 | if (empty) | 2332 | if (empty) |
2328 | nr = 0; | 2333 | nr = 0; |
2329 | else | 2334 | else |
2330 | nr = 1; | 2335 | nr = max_t(u32, 1, min_slot); |
2331 | 2336 | ||
2332 | if (path->slots[0] >= left_nritems) | 2337 | if (path->slots[0] >= left_nritems) |
2333 | push_space += data_size; | 2338 | push_space += data_size; |
@@ -2469,10 +2474,14 @@ out_unlock: | |||
2469 | * | 2474 | * |
2470 | * returns 1 if the push failed because the other node didn't have enough | 2475 | * returns 1 if the push failed because the other node didn't have enough |
2471 | * room, 0 if everything worked out and < 0 if there were major errors. | 2476 | * room, 0 if everything worked out and < 0 if there were major errors. |
2477 | * | ||
2478 | * this will push starting from min_slot to the end of the leaf. It won't | ||
2479 | * push any slot lower than min_slot | ||
2472 | */ | 2480 | */ |
2473 | static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | 2481 | static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root |
2474 | *root, struct btrfs_path *path, int data_size, | 2482 | *root, struct btrfs_path *path, |
2475 | int empty) | 2483 | int min_data_size, int data_size, |
2484 | int empty, u32 min_slot) | ||
2476 | { | 2485 | { |
2477 | struct extent_buffer *left = path->nodes[0]; | 2486 | struct extent_buffer *left = path->nodes[0]; |
2478 | struct extent_buffer *right; | 2487 | struct extent_buffer *right; |
@@ -2514,8 +2523,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
2514 | if (left_nritems == 0) | 2523 | if (left_nritems == 0) |
2515 | goto out_unlock; | 2524 | goto out_unlock; |
2516 | 2525 | ||
2517 | return __push_leaf_right(trans, root, path, data_size, empty, | 2526 | return __push_leaf_right(trans, root, path, min_data_size, empty, |
2518 | right, free_space, left_nritems); | 2527 | right, free_space, left_nritems, min_slot); |
2519 | out_unlock: | 2528 | out_unlock: |
2520 | btrfs_tree_unlock(right); | 2529 | btrfs_tree_unlock(right); |
2521 | free_extent_buffer(right); | 2530 | free_extent_buffer(right); |
@@ -2525,12 +2534,17 @@ out_unlock: | |||
2525 | /* | 2534 | /* |
2526 | * push some data in the path leaf to the left, trying to free up at | 2535 | * push some data in the path leaf to the left, trying to free up at |
2527 | * least data_size bytes. returns zero if the push worked, nonzero otherwise | 2536 | * least data_size bytes. returns zero if the push worked, nonzero otherwise |
2537 | * | ||
2538 | * max_slot can put a limit on how far into the leaf we'll push items. The | ||
2539 | * item at 'max_slot' won't be touched. Use (u32)-1 to make us do all the | ||
2540 | * items | ||
2528 | */ | 2541 | */ |
2529 | static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, | 2542 | static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, |
2530 | struct btrfs_root *root, | 2543 | struct btrfs_root *root, |
2531 | struct btrfs_path *path, int data_size, | 2544 | struct btrfs_path *path, int data_size, |
2532 | int empty, struct extent_buffer *left, | 2545 | int empty, struct extent_buffer *left, |
2533 | int free_space, int right_nritems) | 2546 | int free_space, u32 right_nritems, |
2547 | u32 max_slot) | ||
2534 | { | 2548 | { |
2535 | struct btrfs_disk_key disk_key; | 2549 | struct btrfs_disk_key disk_key; |
2536 | struct extent_buffer *right = path->nodes[0]; | 2550 | struct extent_buffer *right = path->nodes[0]; |
@@ -2549,9 +2563,9 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, | |||
2549 | slot = path->slots[1]; | 2563 | slot = path->slots[1]; |
2550 | 2564 | ||
2551 | if (empty) | 2565 | if (empty) |
2552 | nr = right_nritems; | 2566 | nr = min(right_nritems, max_slot); |
2553 | else | 2567 | else |
2554 | nr = right_nritems - 1; | 2568 | nr = min(right_nritems - 1, max_slot); |
2555 | 2569 | ||
2556 | for (i = 0; i < nr; i++) { | 2570 | for (i = 0; i < nr; i++) { |
2557 | item = btrfs_item_nr(right, i); | 2571 | item = btrfs_item_nr(right, i); |
@@ -2712,10 +2726,14 @@ out: | |||
2712 | /* | 2726 | /* |
2713 | * push some data in the path leaf to the left, trying to free up at | 2727 | * push some data in the path leaf to the left, trying to free up at |
2714 | * least data_size bytes. returns zero if the push worked, nonzero otherwise | 2728 | * least data_size bytes. returns zero if the push worked, nonzero otherwise |
2729 | * | ||
2730 | * max_slot can put a limit on how far into the leaf we'll push items. The | ||
2731 | * item at 'max_slot' won't be touched. Use (u32)-1 to make us push all the | ||
2732 | * items | ||
2715 | */ | 2733 | */ |
2716 | static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | 2734 | static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root |
2717 | *root, struct btrfs_path *path, int data_size, | 2735 | *root, struct btrfs_path *path, int min_data_size, |
2718 | int empty) | 2736 | int data_size, int empty, u32 max_slot) |
2719 | { | 2737 | { |
2720 | struct extent_buffer *right = path->nodes[0]; | 2738 | struct extent_buffer *right = path->nodes[0]; |
2721 | struct extent_buffer *left; | 2739 | struct extent_buffer *left; |
@@ -2761,8 +2779,9 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
2761 | goto out; | 2779 | goto out; |
2762 | } | 2780 | } |
2763 | 2781 | ||
2764 | return __push_leaf_left(trans, root, path, data_size, | 2782 | return __push_leaf_left(trans, root, path, min_data_size, |
2765 | empty, left, free_space, right_nritems); | 2783 | empty, left, free_space, right_nritems, |
2784 | max_slot); | ||
2766 | out: | 2785 | out: |
2767 | btrfs_tree_unlock(left); | 2786 | btrfs_tree_unlock(left); |
2768 | free_extent_buffer(left); | 2787 | free_extent_buffer(left); |
@@ -2855,6 +2874,64 @@ static noinline int copy_for_split(struct btrfs_trans_handle *trans, | |||
2855 | } | 2874 | } |
2856 | 2875 | ||
2857 | /* | 2876 | /* |
2877 | * double splits happen when we need to insert a big item in the middle | ||
2878 | * of a leaf. A double split can leave us with 3 mostly empty leaves: | ||
2879 | * leaf: [ slots 0 - N] [ our target ] [ N + 1 - total in leaf ] | ||
2880 | * A B C | ||
2881 | * | ||
2882 | * We avoid this by trying to push the items on either side of our target | ||
2883 | * into the adjacent leaves. If all goes well we can avoid the double split | ||
2884 | * completely. | ||
2885 | */ | ||
2886 | static noinline int push_for_double_split(struct btrfs_trans_handle *trans, | ||
2887 | struct btrfs_root *root, | ||
2888 | struct btrfs_path *path, | ||
2889 | int data_size) | ||
2890 | { | ||
2891 | int ret; | ||
2892 | int progress = 0; | ||
2893 | int slot; | ||
2894 | u32 nritems; | ||
2895 | |||
2896 | slot = path->slots[0]; | ||
2897 | |||
2898 | /* | ||
2899 | * try to push all the items after our slot into the | ||
2900 | * right leaf | ||
2901 | */ | ||
2902 | ret = push_leaf_right(trans, root, path, 1, data_size, 0, slot); | ||
2903 | if (ret < 0) | ||
2904 | return ret; | ||
2905 | |||
2906 | if (ret == 0) | ||
2907 | progress++; | ||
2908 | |||
2909 | nritems = btrfs_header_nritems(path->nodes[0]); | ||
2910 | /* | ||
2911 | * our goal is to get our slot at the start or end of a leaf. If | ||
2912 | * we've done so we're done | ||
2913 | */ | ||
2914 | if (path->slots[0] == 0 || path->slots[0] == nritems) | ||
2915 | return 0; | ||
2916 | |||
2917 | if (btrfs_leaf_free_space(root, path->nodes[0]) >= data_size) | ||
2918 | return 0; | ||
2919 | |||
2920 | /* try to push all the items before our slot into the next leaf */ | ||
2921 | slot = path->slots[0]; | ||
2922 | ret = push_leaf_left(trans, root, path, 1, data_size, 0, slot); | ||
2923 | if (ret < 0) | ||
2924 | return ret; | ||
2925 | |||
2926 | if (ret == 0) | ||
2927 | progress++; | ||
2928 | |||
2929 | if (progress) | ||
2930 | return 0; | ||
2931 | return 1; | ||
2932 | } | ||
2933 | |||
2934 | /* | ||
2858 | * split the path's leaf in two, making sure there is at least data_size | 2935 | * split the path's leaf in two, making sure there is at least data_size |
2859 | * available for the resulting leaf level of the path. | 2936 | * available for the resulting leaf level of the path. |
2860 | * | 2937 | * |
@@ -2876,6 +2953,7 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, | |||
2876 | int wret; | 2953 | int wret; |
2877 | int split; | 2954 | int split; |
2878 | int num_doubles = 0; | 2955 | int num_doubles = 0; |
2956 | int tried_avoid_double = 0; | ||
2879 | 2957 | ||
2880 | l = path->nodes[0]; | 2958 | l = path->nodes[0]; |
2881 | slot = path->slots[0]; | 2959 | slot = path->slots[0]; |
@@ -2884,12 +2962,14 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, | |||
2884 | return -EOVERFLOW; | 2962 | return -EOVERFLOW; |
2885 | 2963 | ||
2886 | /* first try to make some room by pushing left and right */ | 2964 | /* first try to make some room by pushing left and right */ |
2887 | if (data_size && ins_key->type != BTRFS_DIR_ITEM_KEY) { | 2965 | if (data_size) { |
2888 | wret = push_leaf_right(trans, root, path, data_size, 0); | 2966 | wret = push_leaf_right(trans, root, path, data_size, |
2967 | data_size, 0, 0); | ||
2889 | if (wret < 0) | 2968 | if (wret < 0) |
2890 | return wret; | 2969 | return wret; |
2891 | if (wret) { | 2970 | if (wret) { |
2892 | wret = push_leaf_left(trans, root, path, data_size, 0); | 2971 | wret = push_leaf_left(trans, root, path, data_size, |
2972 | data_size, 0, (u32)-1); | ||
2893 | if (wret < 0) | 2973 | if (wret < 0) |
2894 | return wret; | 2974 | return wret; |
2895 | } | 2975 | } |
@@ -2923,6 +3003,8 @@ again: | |||
2923 | if (mid != nritems && | 3003 | if (mid != nritems && |
2924 | leaf_space_used(l, mid, nritems - mid) + | 3004 | leaf_space_used(l, mid, nritems - mid) + |
2925 | data_size > BTRFS_LEAF_DATA_SIZE(root)) { | 3005 | data_size > BTRFS_LEAF_DATA_SIZE(root)) { |
3006 | if (data_size && !tried_avoid_double) | ||
3007 | goto push_for_double; | ||
2926 | split = 2; | 3008 | split = 2; |
2927 | } | 3009 | } |
2928 | } | 3010 | } |
@@ -2939,6 +3021,8 @@ again: | |||
2939 | if (mid != nritems && | 3021 | if (mid != nritems && |
2940 | leaf_space_used(l, mid, nritems - mid) + | 3022 | leaf_space_used(l, mid, nritems - mid) + |
2941 | data_size > BTRFS_LEAF_DATA_SIZE(root)) { | 3023 | data_size > BTRFS_LEAF_DATA_SIZE(root)) { |
3024 | if (data_size && !tried_avoid_double) | ||
3025 | goto push_for_double; | ||
2942 | split = 2 ; | 3026 | split = 2 ; |
2943 | } | 3027 | } |
2944 | } | 3028 | } |
@@ -3019,6 +3103,13 @@ again: | |||
3019 | } | 3103 | } |
3020 | 3104 | ||
3021 | return ret; | 3105 | return ret; |
3106 | |||
3107 | push_for_double: | ||
3108 | push_for_double_split(trans, root, path, data_size); | ||
3109 | tried_avoid_double = 1; | ||
3110 | if (btrfs_leaf_free_space(root, path->nodes[0]) >= data_size) | ||
3111 | return 0; | ||
3112 | goto again; | ||
3022 | } | 3113 | } |
3023 | 3114 | ||
3024 | static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, | 3115 | static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, |
@@ -3915,13 +4006,15 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
3915 | extent_buffer_get(leaf); | 4006 | extent_buffer_get(leaf); |
3916 | 4007 | ||
3917 | btrfs_set_path_blocking(path); | 4008 | btrfs_set_path_blocking(path); |
3918 | wret = push_leaf_left(trans, root, path, 1, 1); | 4009 | wret = push_leaf_left(trans, root, path, 1, 1, |
4010 | 1, (u32)-1); | ||
3919 | if (wret < 0 && wret != -ENOSPC) | 4011 | if (wret < 0 && wret != -ENOSPC) |
3920 | ret = wret; | 4012 | ret = wret; |
3921 | 4013 | ||
3922 | if (path->nodes[0] == leaf && | 4014 | if (path->nodes[0] == leaf && |
3923 | btrfs_header_nritems(leaf)) { | 4015 | btrfs_header_nritems(leaf)) { |
3924 | wret = push_leaf_right(trans, root, path, 1, 1); | 4016 | wret = push_leaf_right(trans, root, path, 1, |
4017 | 1, 1, 0); | ||
3925 | if (wret < 0 && wret != -ENOSPC) | 4018 | if (wret < 0 && wret != -ENOSPC) |
3926 | ret = wret; | 4019 | ret = wret; |
3927 | } | 4020 | } |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index a4080c21ec55..d74e6af9b53a 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -2594,7 +2594,6 @@ int extent_write_full_page(struct extent_io_tree *tree, struct page *page, | |||
2594 | .sync_io = wbc->sync_mode == WB_SYNC_ALL, | 2594 | .sync_io = wbc->sync_mode == WB_SYNC_ALL, |
2595 | }; | 2595 | }; |
2596 | struct writeback_control wbc_writepages = { | 2596 | struct writeback_control wbc_writepages = { |
2597 | .bdi = wbc->bdi, | ||
2598 | .sync_mode = wbc->sync_mode, | 2597 | .sync_mode = wbc->sync_mode, |
2599 | .older_than_this = NULL, | 2598 | .older_than_this = NULL, |
2600 | .nr_to_write = 64, | 2599 | .nr_to_write = 64, |
@@ -2628,7 +2627,6 @@ int extent_write_locked_range(struct extent_io_tree *tree, struct inode *inode, | |||
2628 | .sync_io = mode == WB_SYNC_ALL, | 2627 | .sync_io = mode == WB_SYNC_ALL, |
2629 | }; | 2628 | }; |
2630 | struct writeback_control wbc_writepages = { | 2629 | struct writeback_control wbc_writepages = { |
2631 | .bdi = inode->i_mapping->backing_dev_info, | ||
2632 | .sync_mode = mode, | 2630 | .sync_mode = mode, |
2633 | .older_than_this = NULL, | 2631 | .older_than_this = NULL, |
2634 | .nr_to_write = nr_pages * 2, | 2632 | .nr_to_write = nr_pages * 2, |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 4dbaf89b1337..9254b3d58dbe 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -1458,7 +1458,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
1458 | */ | 1458 | */ |
1459 | 1459 | ||
1460 | /* the destination must be opened for writing */ | 1460 | /* the destination must be opened for writing */ |
1461 | if (!(file->f_mode & FMODE_WRITE)) | 1461 | if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND)) |
1462 | return -EINVAL; | 1462 | return -EINVAL; |
1463 | 1463 | ||
1464 | ret = mnt_want_write(file->f_path.mnt); | 1464 | ret = mnt_want_write(file->f_path.mnt); |
@@ -1511,7 +1511,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
1511 | 1511 | ||
1512 | /* determine range to clone */ | 1512 | /* determine range to clone */ |
1513 | ret = -EINVAL; | 1513 | ret = -EINVAL; |
1514 | if (off >= src->i_size || off + len > src->i_size) | 1514 | if (off + len > src->i_size || off + len < off) |
1515 | goto out_unlock; | 1515 | goto out_unlock; |
1516 | if (len == 0) | 1516 | if (len == 0) |
1517 | olen = len = src->i_size - off; | 1517 | olen = len = src->i_size - off; |
@@ -1578,6 +1578,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
1578 | u64 disko = 0, diskl = 0; | 1578 | u64 disko = 0, diskl = 0; |
1579 | u64 datao = 0, datal = 0; | 1579 | u64 datao = 0, datal = 0; |
1580 | u8 comp; | 1580 | u8 comp; |
1581 | u64 endoff; | ||
1581 | 1582 | ||
1582 | size = btrfs_item_size_nr(leaf, slot); | 1583 | size = btrfs_item_size_nr(leaf, slot); |
1583 | read_extent_buffer(leaf, buf, | 1584 | read_extent_buffer(leaf, buf, |
@@ -1712,9 +1713,18 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
1712 | btrfs_release_path(root, path); | 1713 | btrfs_release_path(root, path); |
1713 | 1714 | ||
1714 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 1715 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
1715 | if (new_key.offset + datal > inode->i_size) | 1716 | |
1716 | btrfs_i_size_write(inode, | 1717 | /* |
1717 | new_key.offset + datal); | 1718 | * we round up to the block size at eof when |
1719 | * determining which extents to clone above, | ||
1720 | * but shouldn't round up the file size | ||
1721 | */ | ||
1722 | endoff = new_key.offset + datal; | ||
1723 | if (endoff > off+olen) | ||
1724 | endoff = off+olen; | ||
1725 | if (endoff > inode->i_size) | ||
1726 | btrfs_i_size_write(inode, endoff); | ||
1727 | |||
1718 | BTRFS_I(inode)->flags = BTRFS_I(src)->flags; | 1728 | BTRFS_I(inode)->flags = BTRFS_I(src)->flags; |
1719 | ret = btrfs_update_inode(trans, root, inode); | 1729 | ret = btrfs_update_inode(trans, root, inode); |
1720 | BUG_ON(ret); | 1730 | BUG_ON(ret); |
diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index f4a7840bf42c..42c7fafc8bfe 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c | |||
@@ -37,9 +37,9 @@ void __cachefiles_printk_object(struct cachefiles_object *object, | |||
37 | 37 | ||
38 | printk(KERN_ERR "%sobject: OBJ%x\n", | 38 | printk(KERN_ERR "%sobject: OBJ%x\n", |
39 | prefix, object->fscache.debug_id); | 39 | prefix, object->fscache.debug_id); |
40 | printk(KERN_ERR "%sobjstate=%s fl=%lx swfl=%lx ev=%lx[%lx]\n", | 40 | printk(KERN_ERR "%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n", |
41 | prefix, fscache_object_states[object->fscache.state], | 41 | prefix, fscache_object_states[object->fscache.state], |
42 | object->fscache.flags, object->fscache.work.flags, | 42 | object->fscache.flags, work_busy(&object->fscache.work), |
43 | object->fscache.events, | 43 | object->fscache.events, |
44 | object->fscache.event_mask & FSCACHE_OBJECT_EVENTS_MASK); | 44 | object->fscache.event_mask & FSCACHE_OBJECT_EVENTS_MASK); |
45 | printk(KERN_ERR "%sops=%u inp=%u exc=%u\n", | 45 | printk(KERN_ERR "%sops=%u inp=%u exc=%u\n", |
@@ -212,7 +212,7 @@ wait_for_old_object: | |||
212 | 212 | ||
213 | /* if the object we're waiting for is queued for processing, | 213 | /* if the object we're waiting for is queued for processing, |
214 | * then just put ourselves on the queue behind it */ | 214 | * then just put ourselves on the queue behind it */ |
215 | if (slow_work_is_queued(&xobject->fscache.work)) { | 215 | if (work_pending(&xobject->fscache.work)) { |
216 | _debug("queue OBJ%x behind OBJ%x immediately", | 216 | _debug("queue OBJ%x behind OBJ%x immediately", |
217 | object->fscache.debug_id, | 217 | object->fscache.debug_id, |
218 | xobject->fscache.debug_id); | 218 | xobject->fscache.debug_id); |
@@ -220,8 +220,7 @@ wait_for_old_object: | |||
220 | } | 220 | } |
221 | 221 | ||
222 | /* otherwise we sleep until either the object we're waiting for | 222 | /* otherwise we sleep until either the object we're waiting for |
223 | * is done, or the slow-work facility wants the thread back to | 223 | * is done, or the fscache_object is congested */ |
224 | * do other work */ | ||
225 | wq = bit_waitqueue(&xobject->flags, CACHEFILES_OBJECT_ACTIVE); | 224 | wq = bit_waitqueue(&xobject->flags, CACHEFILES_OBJECT_ACTIVE); |
226 | init_wait(&wait); | 225 | init_wait(&wait); |
227 | requeue = false; | 226 | requeue = false; |
@@ -229,8 +228,8 @@ wait_for_old_object: | |||
229 | prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE); | 228 | prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE); |
230 | if (!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)) | 229 | if (!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags)) |
231 | break; | 230 | break; |
232 | requeue = slow_work_sleep_till_thread_needed( | 231 | |
233 | &object->fscache.work, &timeout); | 232 | requeue = fscache_object_sleep_till_congested(&timeout); |
234 | } while (timeout > 0 && !requeue); | 233 | } while (timeout > 0 && !requeue); |
235 | finish_wait(wq, &wait); | 234 | finish_wait(wq, &wait); |
236 | 235 | ||
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index 0f0d41fbb03f..0e3c0924cc3a 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c | |||
@@ -422,7 +422,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op, | |||
422 | shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits; | 422 | shift = PAGE_SHIFT - inode->i_sb->s_blocksize_bits; |
423 | 423 | ||
424 | op->op.flags &= FSCACHE_OP_KEEP_FLAGS; | 424 | op->op.flags &= FSCACHE_OP_KEEP_FLAGS; |
425 | op->op.flags |= FSCACHE_OP_FAST; | 425 | op->op.flags |= FSCACHE_OP_ASYNC; |
426 | op->op.processor = cachefiles_read_copier; | 426 | op->op.processor = cachefiles_read_copier; |
427 | 427 | ||
428 | pagevec_init(&pagevec, 0); | 428 | pagevec_init(&pagevec, 0); |
@@ -729,7 +729,7 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op, | |||
729 | pagevec_init(&pagevec, 0); | 729 | pagevec_init(&pagevec, 0); |
730 | 730 | ||
731 | op->op.flags &= FSCACHE_OP_KEEP_FLAGS; | 731 | op->op.flags &= FSCACHE_OP_KEEP_FLAGS; |
732 | op->op.flags |= FSCACHE_OP_FAST; | 732 | op->op.flags |= FSCACHE_OP_ASYNC; |
733 | op->op.processor = cachefiles_read_copier; | 733 | op->op.processor = cachefiles_read_copier; |
734 | 734 | ||
735 | INIT_LIST_HEAD(&backpages); | 735 | INIT_LIST_HEAD(&backpages); |
diff --git a/fs/ceph/Kconfig b/fs/ceph/Kconfig index 04b8280582a9..bc87b9c1d27e 100644 --- a/fs/ceph/Kconfig +++ b/fs/ceph/Kconfig | |||
@@ -2,7 +2,7 @@ config CEPH_FS | |||
2 | tristate "Ceph distributed file system (EXPERIMENTAL)" | 2 | tristate "Ceph distributed file system (EXPERIMENTAL)" |
3 | depends on INET && EXPERIMENTAL | 3 | depends on INET && EXPERIMENTAL |
4 | select LIBCRC32C | 4 | select LIBCRC32C |
5 | select CONFIG_CRYPTO_AES | 5 | select CRYPTO_AES |
6 | help | 6 | help |
7 | Choose Y or M here to include support for mounting the | 7 | Choose Y or M here to include support for mounting the |
8 | experimental Ceph distributed file system. Ceph is an extremely | 8 | experimental Ceph distributed file system. Ceph is an extremely |
diff --git a/fs/ceph/auth_x.c b/fs/ceph/auth_x.c index 83d4d2785ffe..6d44053ecff1 100644 --- a/fs/ceph/auth_x.c +++ b/fs/ceph/auth_x.c | |||
@@ -493,7 +493,7 @@ static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result, | |||
493 | return -EAGAIN; | 493 | return -EAGAIN; |
494 | } | 494 | } |
495 | 495 | ||
496 | op = le32_to_cpu(head->op); | 496 | op = le16_to_cpu(head->op); |
497 | result = le32_to_cpu(head->result); | 497 | result = le32_to_cpu(head->result); |
498 | dout("handle_reply op %d result %d\n", op, result); | 498 | dout("handle_reply op %d result %d\n", op, result); |
499 | switch (op) { | 499 | switch (op) { |
@@ -613,6 +613,9 @@ static void ceph_x_destroy(struct ceph_auth_client *ac) | |||
613 | remove_ticket_handler(ac, th); | 613 | remove_ticket_handler(ac, th); |
614 | } | 614 | } |
615 | 615 | ||
616 | if (xi->auth_authorizer.buf) | ||
617 | ceph_buffer_put(xi->auth_authorizer.buf); | ||
618 | |||
616 | kfree(ac->private); | 619 | kfree(ac->private); |
617 | ac->private = NULL; | 620 | ac->private = NULL; |
618 | } | 621 | } |
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 619b61655ee5..b81be9a56487 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -244,8 +244,14 @@ static struct ceph_cap *get_cap(struct ceph_cap_reservation *ctx) | |||
244 | struct ceph_cap *cap = NULL; | 244 | struct ceph_cap *cap = NULL; |
245 | 245 | ||
246 | /* temporary, until we do something about cap import/export */ | 246 | /* temporary, until we do something about cap import/export */ |
247 | if (!ctx) | 247 | if (!ctx) { |
248 | return kmem_cache_alloc(ceph_cap_cachep, GFP_NOFS); | 248 | cap = kmem_cache_alloc(ceph_cap_cachep, GFP_NOFS); |
249 | if (cap) { | ||
250 | caps_use_count++; | ||
251 | caps_total_count++; | ||
252 | } | ||
253 | return cap; | ||
254 | } | ||
249 | 255 | ||
250 | spin_lock(&caps_list_lock); | 256 | spin_lock(&caps_list_lock); |
251 | dout("get_cap ctx=%p (%d) %d = %d used + %d resv + %d avail\n", | 257 | dout("get_cap ctx=%p (%d) %d = %d used + %d resv + %d avail\n", |
@@ -621,7 +627,7 @@ retry: | |||
621 | if (fmode >= 0) | 627 | if (fmode >= 0) |
622 | __ceph_get_fmode(ci, fmode); | 628 | __ceph_get_fmode(ci, fmode); |
623 | spin_unlock(&inode->i_lock); | 629 | spin_unlock(&inode->i_lock); |
624 | wake_up(&ci->i_cap_wq); | 630 | wake_up_all(&ci->i_cap_wq); |
625 | return 0; | 631 | return 0; |
626 | } | 632 | } |
627 | 633 | ||
@@ -1175,7 +1181,7 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, | |||
1175 | } | 1181 | } |
1176 | 1182 | ||
1177 | if (wake) | 1183 | if (wake) |
1178 | wake_up(&ci->i_cap_wq); | 1184 | wake_up_all(&ci->i_cap_wq); |
1179 | 1185 | ||
1180 | return delayed; | 1186 | return delayed; |
1181 | } | 1187 | } |
@@ -2147,7 +2153,7 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had) | |||
2147 | else if (flushsnaps) | 2153 | else if (flushsnaps) |
2148 | ceph_flush_snaps(ci); | 2154 | ceph_flush_snaps(ci); |
2149 | if (wake) | 2155 | if (wake) |
2150 | wake_up(&ci->i_cap_wq); | 2156 | wake_up_all(&ci->i_cap_wq); |
2151 | if (put) | 2157 | if (put) |
2152 | iput(inode); | 2158 | iput(inode); |
2153 | } | 2159 | } |
@@ -2223,7 +2229,7 @@ void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, | |||
2223 | iput(inode); | 2229 | iput(inode); |
2224 | } else if (complete_capsnap) { | 2230 | } else if (complete_capsnap) { |
2225 | ceph_flush_snaps(ci); | 2231 | ceph_flush_snaps(ci); |
2226 | wake_up(&ci->i_cap_wq); | 2232 | wake_up_all(&ci->i_cap_wq); |
2227 | } | 2233 | } |
2228 | if (drop_capsnap) | 2234 | if (drop_capsnap) |
2229 | iput(inode); | 2235 | iput(inode); |
@@ -2399,7 +2405,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, | |||
2399 | if (queue_invalidate) | 2405 | if (queue_invalidate) |
2400 | ceph_queue_invalidate(inode); | 2406 | ceph_queue_invalidate(inode); |
2401 | if (wake) | 2407 | if (wake) |
2402 | wake_up(&ci->i_cap_wq); | 2408 | wake_up_all(&ci->i_cap_wq); |
2403 | 2409 | ||
2404 | if (check_caps == 1) | 2410 | if (check_caps == 1) |
2405 | ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_AUTHONLY, | 2411 | ceph_check_caps(ci, CHECK_CAPS_NODELAY|CHECK_CAPS_AUTHONLY, |
@@ -2454,7 +2460,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid, | |||
2454 | struct ceph_inode_info, | 2460 | struct ceph_inode_info, |
2455 | i_flushing_item)->vfs_inode); | 2461 | i_flushing_item)->vfs_inode); |
2456 | mdsc->num_cap_flushing--; | 2462 | mdsc->num_cap_flushing--; |
2457 | wake_up(&mdsc->cap_flushing_wq); | 2463 | wake_up_all(&mdsc->cap_flushing_wq); |
2458 | dout(" inode %p now !flushing\n", inode); | 2464 | dout(" inode %p now !flushing\n", inode); |
2459 | 2465 | ||
2460 | if (ci->i_dirty_caps == 0) { | 2466 | if (ci->i_dirty_caps == 0) { |
@@ -2466,7 +2472,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid, | |||
2466 | } | 2472 | } |
2467 | } | 2473 | } |
2468 | spin_unlock(&mdsc->cap_dirty_lock); | 2474 | spin_unlock(&mdsc->cap_dirty_lock); |
2469 | wake_up(&ci->i_cap_wq); | 2475 | wake_up_all(&ci->i_cap_wq); |
2470 | 2476 | ||
2471 | out: | 2477 | out: |
2472 | spin_unlock(&inode->i_lock); | 2478 | spin_unlock(&inode->i_lock); |
@@ -2886,18 +2892,19 @@ int ceph_encode_inode_release(void **p, struct inode *inode, | |||
2886 | struct ceph_inode_info *ci = ceph_inode(inode); | 2892 | struct ceph_inode_info *ci = ceph_inode(inode); |
2887 | struct ceph_cap *cap; | 2893 | struct ceph_cap *cap; |
2888 | struct ceph_mds_request_release *rel = *p; | 2894 | struct ceph_mds_request_release *rel = *p; |
2895 | int used, dirty; | ||
2889 | int ret = 0; | 2896 | int ret = 0; |
2890 | int used = 0; | ||
2891 | 2897 | ||
2892 | spin_lock(&inode->i_lock); | 2898 | spin_lock(&inode->i_lock); |
2893 | used = __ceph_caps_used(ci); | 2899 | used = __ceph_caps_used(ci); |
2900 | dirty = __ceph_caps_dirty(ci); | ||
2894 | 2901 | ||
2895 | dout("encode_inode_release %p mds%d used %s drop %s unless %s\n", inode, | 2902 | dout("encode_inode_release %p mds%d used|dirty %s drop %s unless %s\n", |
2896 | mds, ceph_cap_string(used), ceph_cap_string(drop), | 2903 | inode, mds, ceph_cap_string(used|dirty), ceph_cap_string(drop), |
2897 | ceph_cap_string(unless)); | 2904 | ceph_cap_string(unless)); |
2898 | 2905 | ||
2899 | /* only drop unused caps */ | 2906 | /* only drop unused, clean caps */ |
2900 | drop &= ~used; | 2907 | drop &= ~(used | dirty); |
2901 | 2908 | ||
2902 | cap = __get_cap_for_mds(ci, mds); | 2909 | cap = __get_cap_for_mds(ci, mds); |
2903 | if (cap && __cap_is_valid(cap)) { | 2910 | if (cap && __cap_is_valid(cap)) { |
@@ -2977,6 +2984,7 @@ int ceph_encode_dentry_release(void **p, struct dentry *dentry, | |||
2977 | memcpy(*p, dentry->d_name.name, dentry->d_name.len); | 2984 | memcpy(*p, dentry->d_name.name, dentry->d_name.len); |
2978 | *p += dentry->d_name.len; | 2985 | *p += dentry->d_name.len; |
2979 | rel->dname_seq = cpu_to_le32(di->lease_seq); | 2986 | rel->dname_seq = cpu_to_le32(di->lease_seq); |
2987 | __ceph_mdsc_drop_dentry_lease(dentry); | ||
2980 | } | 2988 | } |
2981 | spin_unlock(&dentry->d_lock); | 2989 | spin_unlock(&dentry->d_lock); |
2982 | return ret; | 2990 | return ret; |
diff --git a/fs/ceph/crush/mapper.c b/fs/ceph/crush/mapper.c index 9ba54efb6543..a4eec133258e 100644 --- a/fs/ceph/crush/mapper.c +++ b/fs/ceph/crush/mapper.c | |||
@@ -238,7 +238,7 @@ static int bucket_straw_choose(struct crush_bucket_straw *bucket, | |||
238 | 238 | ||
239 | static int crush_bucket_choose(struct crush_bucket *in, int x, int r) | 239 | static int crush_bucket_choose(struct crush_bucket *in, int x, int r) |
240 | { | 240 | { |
241 | dprintk("choose %d x=%d r=%d\n", in->id, x, r); | 241 | dprintk(" crush_bucket_choose %d x=%d r=%d\n", in->id, x, r); |
242 | switch (in->alg) { | 242 | switch (in->alg) { |
243 | case CRUSH_BUCKET_UNIFORM: | 243 | case CRUSH_BUCKET_UNIFORM: |
244 | return bucket_uniform_choose((struct crush_bucket_uniform *)in, | 244 | return bucket_uniform_choose((struct crush_bucket_uniform *)in, |
@@ -264,7 +264,7 @@ static int crush_bucket_choose(struct crush_bucket *in, int x, int r) | |||
264 | */ | 264 | */ |
265 | static int is_out(struct crush_map *map, __u32 *weight, int item, int x) | 265 | static int is_out(struct crush_map *map, __u32 *weight, int item, int x) |
266 | { | 266 | { |
267 | if (weight[item] >= 0x1000) | 267 | if (weight[item] >= 0x10000) |
268 | return 0; | 268 | return 0; |
269 | if (weight[item] == 0) | 269 | if (weight[item] == 0) |
270 | return 1; | 270 | return 1; |
@@ -305,7 +305,9 @@ static int crush_choose(struct crush_map *map, | |||
305 | int itemtype; | 305 | int itemtype; |
306 | int collide, reject; | 306 | int collide, reject; |
307 | const int orig_tries = 5; /* attempts before we fall back to search */ | 307 | const int orig_tries = 5; /* attempts before we fall back to search */ |
308 | dprintk("choose bucket %d x %d outpos %d\n", bucket->id, x, outpos); | 308 | |
309 | dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "", | ||
310 | bucket->id, x, outpos, numrep); | ||
309 | 311 | ||
310 | for (rep = outpos; rep < numrep; rep++) { | 312 | for (rep = outpos; rep < numrep; rep++) { |
311 | /* keep trying until we get a non-out, non-colliding item */ | 313 | /* keep trying until we get a non-out, non-colliding item */ |
@@ -366,6 +368,7 @@ static int crush_choose(struct crush_map *map, | |||
366 | BUG_ON(item >= 0 || | 368 | BUG_ON(item >= 0 || |
367 | (-1-item) >= map->max_buckets); | 369 | (-1-item) >= map->max_buckets); |
368 | in = map->buckets[-1-item]; | 370 | in = map->buckets[-1-item]; |
371 | retry_bucket = 1; | ||
369 | continue; | 372 | continue; |
370 | } | 373 | } |
371 | 374 | ||
@@ -377,15 +380,25 @@ static int crush_choose(struct crush_map *map, | |||
377 | } | 380 | } |
378 | } | 381 | } |
379 | 382 | ||
380 | if (recurse_to_leaf && | 383 | reject = 0; |
381 | item < 0 && | 384 | if (recurse_to_leaf) { |
382 | crush_choose(map, map->buckets[-1-item], | 385 | if (item < 0) { |
383 | weight, | 386 | if (crush_choose(map, |
384 | x, outpos+1, 0, | 387 | map->buckets[-1-item], |
385 | out2, outpos, | 388 | weight, |
386 | firstn, 0, NULL) <= outpos) { | 389 | x, outpos+1, 0, |
387 | reject = 1; | 390 | out2, outpos, |
388 | } else { | 391 | firstn, 0, |
392 | NULL) <= outpos) | ||
393 | /* didn't get leaf */ | ||
394 | reject = 1; | ||
395 | } else { | ||
396 | /* we already have a leaf! */ | ||
397 | out2[outpos] = item; | ||
398 | } | ||
399 | } | ||
400 | |||
401 | if (!reject) { | ||
389 | /* out? */ | 402 | /* out? */ |
390 | if (itemtype == 0) | 403 | if (itemtype == 0) |
391 | reject = is_out(map, weight, | 404 | reject = is_out(map, weight, |
@@ -424,12 +437,12 @@ reject: | |||
424 | continue; | 437 | continue; |
425 | } | 438 | } |
426 | 439 | ||
427 | dprintk("choose got %d\n", item); | 440 | dprintk("CHOOSE got %d\n", item); |
428 | out[outpos] = item; | 441 | out[outpos] = item; |
429 | outpos++; | 442 | outpos++; |
430 | } | 443 | } |
431 | 444 | ||
432 | dprintk("choose returns %d\n", outpos); | 445 | dprintk("CHOOSE returns %d\n", outpos); |
433 | return outpos; | 446 | return outpos; |
434 | } | 447 | } |
435 | 448 | ||
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index 3be33fb066cc..f2f5332ddbba 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c | |||
@@ -261,7 +261,7 @@ static int osdc_show(struct seq_file *s, void *pp) | |||
261 | 261 | ||
262 | static int caps_show(struct seq_file *s, void *p) | 262 | static int caps_show(struct seq_file *s, void *p) |
263 | { | 263 | { |
264 | struct ceph_client *client = p; | 264 | struct ceph_client *client = s->private; |
265 | int total, avail, used, reserved, min; | 265 | int total, avail, used, reserved, min; |
266 | 266 | ||
267 | ceph_reservation_status(client, &total, &avail, &used, &reserved, &min); | 267 | ceph_reservation_status(client, &total, &avail, &used, &reserved, &min); |
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index f85719310db2..f94ed3c7f6a5 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -266,6 +266,7 @@ static int ceph_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
266 | spin_lock(&inode->i_lock); | 266 | spin_lock(&inode->i_lock); |
267 | if ((filp->f_pos == 2 || fi->dentry) && | 267 | if ((filp->f_pos == 2 || fi->dentry) && |
268 | !ceph_test_opt(client, NOASYNCREADDIR) && | 268 | !ceph_test_opt(client, NOASYNCREADDIR) && |
269 | ceph_snap(inode) != CEPH_SNAPDIR && | ||
269 | (ci->i_ceph_flags & CEPH_I_COMPLETE) && | 270 | (ci->i_ceph_flags & CEPH_I_COMPLETE) && |
270 | __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { | 271 | __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { |
271 | err = __dcache_readdir(filp, dirent, filldir); | 272 | err = __dcache_readdir(filp, dirent, filldir); |
@@ -1013,18 +1014,22 @@ out_touch: | |||
1013 | 1014 | ||
1014 | /* | 1015 | /* |
1015 | * When a dentry is released, clear the dir I_COMPLETE if it was part | 1016 | * When a dentry is released, clear the dir I_COMPLETE if it was part |
1016 | * of the current dir gen. | 1017 | * of the current dir gen or if this is in the snapshot namespace. |
1017 | */ | 1018 | */ |
1018 | static void ceph_dentry_release(struct dentry *dentry) | 1019 | static void ceph_dentry_release(struct dentry *dentry) |
1019 | { | 1020 | { |
1020 | struct ceph_dentry_info *di = ceph_dentry(dentry); | 1021 | struct ceph_dentry_info *di = ceph_dentry(dentry); |
1021 | struct inode *parent_inode = dentry->d_parent->d_inode; | 1022 | struct inode *parent_inode = dentry->d_parent->d_inode; |
1023 | u64 snapid = ceph_snap(parent_inode); | ||
1022 | 1024 | ||
1023 | if (parent_inode) { | 1025 | dout("dentry_release %p parent %p\n", dentry, parent_inode); |
1026 | |||
1027 | if (parent_inode && snapid != CEPH_SNAPDIR) { | ||
1024 | struct ceph_inode_info *ci = ceph_inode(parent_inode); | 1028 | struct ceph_inode_info *ci = ceph_inode(parent_inode); |
1025 | 1029 | ||
1026 | spin_lock(&parent_inode->i_lock); | 1030 | spin_lock(&parent_inode->i_lock); |
1027 | if (ci->i_shared_gen == di->lease_shared_gen) { | 1031 | if (ci->i_shared_gen == di->lease_shared_gen || |
1032 | snapid <= CEPH_MAXSNAP) { | ||
1028 | dout(" clearing %p complete (d_release)\n", | 1033 | dout(" clearing %p complete (d_release)\n", |
1029 | parent_inode); | 1034 | parent_inode); |
1030 | ci->i_ceph_flags &= ~CEPH_I_COMPLETE; | 1035 | ci->i_ceph_flags &= ~CEPH_I_COMPLETE; |
@@ -1241,7 +1246,9 @@ struct dentry_operations ceph_dentry_ops = { | |||
1241 | 1246 | ||
1242 | struct dentry_operations ceph_snapdir_dentry_ops = { | 1247 | struct dentry_operations ceph_snapdir_dentry_ops = { |
1243 | .d_revalidate = ceph_snapdir_d_revalidate, | 1248 | .d_revalidate = ceph_snapdir_d_revalidate, |
1249 | .d_release = ceph_dentry_release, | ||
1244 | }; | 1250 | }; |
1245 | 1251 | ||
1246 | struct dentry_operations ceph_snap_dentry_ops = { | 1252 | struct dentry_operations ceph_snap_dentry_ops = { |
1253 | .d_release = ceph_dentry_release, | ||
1247 | }; | 1254 | }; |
diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 6251a1574b94..7c08698fad3e 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c | |||
@@ -265,7 +265,7 @@ int ceph_release(struct inode *inode, struct file *file) | |||
265 | kmem_cache_free(ceph_file_cachep, cf); | 265 | kmem_cache_free(ceph_file_cachep, cf); |
266 | 266 | ||
267 | /* wake up anyone waiting for caps on this inode */ | 267 | /* wake up anyone waiting for caps on this inode */ |
268 | wake_up(&ci->i_cap_wq); | 268 | wake_up_all(&ci->i_cap_wq); |
269 | return 0; | 269 | return 0; |
270 | } | 270 | } |
271 | 271 | ||
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index ab47f46ca282..389f9dbd9949 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c | |||
@@ -854,8 +854,8 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in, | |||
854 | d_drop(dn); | 854 | d_drop(dn); |
855 | realdn = d_materialise_unique(dn, in); | 855 | realdn = d_materialise_unique(dn, in); |
856 | if (IS_ERR(realdn)) { | 856 | if (IS_ERR(realdn)) { |
857 | pr_err("splice_dentry error %p inode %p ino %llx.%llx\n", | 857 | pr_err("splice_dentry error %ld %p inode %p ino %llx.%llx\n", |
858 | dn, in, ceph_vinop(in)); | 858 | PTR_ERR(realdn), dn, in, ceph_vinop(in)); |
859 | if (prehash) | 859 | if (prehash) |
860 | *prehash = false; /* don't rehash on error */ | 860 | *prehash = false; /* don't rehash on error */ |
861 | dn = realdn; /* note realdn contains the error */ | 861 | dn = realdn; /* note realdn contains the error */ |
@@ -1199,8 +1199,10 @@ retry_lookup: | |||
1199 | goto out; | 1199 | goto out; |
1200 | } | 1200 | } |
1201 | err = ceph_init_dentry(dn); | 1201 | err = ceph_init_dentry(dn); |
1202 | if (err < 0) | 1202 | if (err < 0) { |
1203 | dput(dn); | ||
1203 | goto out; | 1204 | goto out; |
1205 | } | ||
1204 | } else if (dn->d_inode && | 1206 | } else if (dn->d_inode && |
1205 | (ceph_ino(dn->d_inode) != vino.ino || | 1207 | (ceph_ino(dn->d_inode) != vino.ino || |
1206 | ceph_snap(dn->d_inode) != vino.snap)) { | 1208 | ceph_snap(dn->d_inode) != vino.snap)) { |
@@ -1234,18 +1236,23 @@ retry_lookup: | |||
1234 | goto out; | 1236 | goto out; |
1235 | } | 1237 | } |
1236 | dn = splice_dentry(dn, in, NULL); | 1238 | dn = splice_dentry(dn, in, NULL); |
1239 | if (IS_ERR(dn)) | ||
1240 | dn = NULL; | ||
1237 | } | 1241 | } |
1238 | 1242 | ||
1239 | if (fill_inode(in, &rinfo->dir_in[i], NULL, session, | 1243 | if (fill_inode(in, &rinfo->dir_in[i], NULL, session, |
1240 | req->r_request_started, -1, | 1244 | req->r_request_started, -1, |
1241 | &req->r_caps_reservation) < 0) { | 1245 | &req->r_caps_reservation) < 0) { |
1242 | pr_err("fill_inode badness on %p\n", in); | 1246 | pr_err("fill_inode badness on %p\n", in); |
1243 | dput(dn); | 1247 | goto next_item; |
1244 | continue; | ||
1245 | } | 1248 | } |
1246 | update_dentry_lease(dn, rinfo->dir_dlease[i], | 1249 | if (dn) |
1247 | req->r_session, req->r_request_started); | 1250 | update_dentry_lease(dn, rinfo->dir_dlease[i], |
1248 | dput(dn); | 1251 | req->r_session, |
1252 | req->r_request_started); | ||
1253 | next_item: | ||
1254 | if (dn) | ||
1255 | dput(dn); | ||
1249 | } | 1256 | } |
1250 | req->r_did_prepopulate = true; | 1257 | req->r_did_prepopulate = true; |
1251 | 1258 | ||
@@ -1494,7 +1501,7 @@ retry: | |||
1494 | if (wrbuffer_refs == 0) | 1501 | if (wrbuffer_refs == 0) |
1495 | ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); | 1502 | ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); |
1496 | if (wake) | 1503 | if (wake) |
1497 | wake_up(&ci->i_cap_wq); | 1504 | wake_up_all(&ci->i_cap_wq); |
1498 | } | 1505 | } |
1499 | 1506 | ||
1500 | 1507 | ||
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 1766947fc07a..dd440bd438a9 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -868,7 +868,7 @@ static int wake_up_session_cb(struct inode *inode, struct ceph_cap *cap, | |||
868 | { | 868 | { |
869 | struct ceph_inode_info *ci = ceph_inode(inode); | 869 | struct ceph_inode_info *ci = ceph_inode(inode); |
870 | 870 | ||
871 | wake_up(&ci->i_cap_wq); | 871 | wake_up_all(&ci->i_cap_wq); |
872 | if (arg) { | 872 | if (arg) { |
873 | spin_lock(&inode->i_lock); | 873 | spin_lock(&inode->i_lock); |
874 | ci->i_wanted_max_size = 0; | 874 | ci->i_wanted_max_size = 0; |
@@ -1514,6 +1514,9 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, | |||
1514 | ceph_encode_filepath(&p, end, ino1, path1); | 1514 | ceph_encode_filepath(&p, end, ino1, path1); |
1515 | ceph_encode_filepath(&p, end, ino2, path2); | 1515 | ceph_encode_filepath(&p, end, ino2, path2); |
1516 | 1516 | ||
1517 | /* make note of release offset, in case we need to replay */ | ||
1518 | req->r_request_release_offset = p - msg->front.iov_base; | ||
1519 | |||
1517 | /* cap releases */ | 1520 | /* cap releases */ |
1518 | releases = 0; | 1521 | releases = 0; |
1519 | if (req->r_inode_drop) | 1522 | if (req->r_inode_drop) |
@@ -1561,7 +1564,7 @@ static void complete_request(struct ceph_mds_client *mdsc, | |||
1561 | if (req->r_callback) | 1564 | if (req->r_callback) |
1562 | req->r_callback(mdsc, req); | 1565 | req->r_callback(mdsc, req); |
1563 | else | 1566 | else |
1564 | complete(&req->r_completion); | 1567 | complete_all(&req->r_completion); |
1565 | } | 1568 | } |
1566 | 1569 | ||
1567 | /* | 1570 | /* |
@@ -1580,6 +1583,32 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc, | |||
1580 | dout("prepare_send_request %p tid %lld %s (attempt %d)\n", req, | 1583 | dout("prepare_send_request %p tid %lld %s (attempt %d)\n", req, |
1581 | req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts); | 1584 | req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts); |
1582 | 1585 | ||
1586 | if (req->r_got_unsafe) { | ||
1587 | /* | ||
1588 | * Replay. Do not regenerate message (and rebuild | ||
1589 | * paths, etc.); just use the original message. | ||
1590 | * Rebuilding paths will break for renames because | ||
1591 | * d_move mangles the src name. | ||
1592 | */ | ||
1593 | msg = req->r_request; | ||
1594 | rhead = msg->front.iov_base; | ||
1595 | |||
1596 | flags = le32_to_cpu(rhead->flags); | ||
1597 | flags |= CEPH_MDS_FLAG_REPLAY; | ||
1598 | rhead->flags = cpu_to_le32(flags); | ||
1599 | |||
1600 | if (req->r_target_inode) | ||
1601 | rhead->ino = cpu_to_le64(ceph_ino(req->r_target_inode)); | ||
1602 | |||
1603 | rhead->num_retry = req->r_attempts - 1; | ||
1604 | |||
1605 | /* remove cap/dentry releases from message */ | ||
1606 | rhead->num_releases = 0; | ||
1607 | msg->hdr.front_len = cpu_to_le32(req->r_request_release_offset); | ||
1608 | msg->front.iov_len = req->r_request_release_offset; | ||
1609 | return 0; | ||
1610 | } | ||
1611 | |||
1583 | if (req->r_request) { | 1612 | if (req->r_request) { |
1584 | ceph_msg_put(req->r_request); | 1613 | ceph_msg_put(req->r_request); |
1585 | req->r_request = NULL; | 1614 | req->r_request = NULL; |
@@ -1601,13 +1630,9 @@ static int __prepare_send_request(struct ceph_mds_client *mdsc, | |||
1601 | rhead->flags = cpu_to_le32(flags); | 1630 | rhead->flags = cpu_to_le32(flags); |
1602 | rhead->num_fwd = req->r_num_fwd; | 1631 | rhead->num_fwd = req->r_num_fwd; |
1603 | rhead->num_retry = req->r_attempts - 1; | 1632 | rhead->num_retry = req->r_attempts - 1; |
1633 | rhead->ino = 0; | ||
1604 | 1634 | ||
1605 | dout(" r_locked_dir = %p\n", req->r_locked_dir); | 1635 | dout(" r_locked_dir = %p\n", req->r_locked_dir); |
1606 | |||
1607 | if (req->r_target_inode && req->r_got_unsafe) | ||
1608 | rhead->ino = cpu_to_le64(ceph_ino(req->r_target_inode)); | ||
1609 | else | ||
1610 | rhead->ino = 0; | ||
1611 | return 0; | 1636 | return 0; |
1612 | } | 1637 | } |
1613 | 1638 | ||
@@ -1907,7 +1932,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
1907 | if (head->safe) { | 1932 | if (head->safe) { |
1908 | req->r_got_safe = true; | 1933 | req->r_got_safe = true; |
1909 | __unregister_request(mdsc, req); | 1934 | __unregister_request(mdsc, req); |
1910 | complete(&req->r_safe_completion); | 1935 | complete_all(&req->r_safe_completion); |
1911 | 1936 | ||
1912 | if (req->r_got_unsafe) { | 1937 | if (req->r_got_unsafe) { |
1913 | /* | 1938 | /* |
@@ -1922,7 +1947,7 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) | |||
1922 | 1947 | ||
1923 | /* last unsafe request during umount? */ | 1948 | /* last unsafe request during umount? */ |
1924 | if (mdsc->stopping && !__get_oldest_req(mdsc)) | 1949 | if (mdsc->stopping && !__get_oldest_req(mdsc)) |
1925 | complete(&mdsc->safe_umount_waiters); | 1950 | complete_all(&mdsc->safe_umount_waiters); |
1926 | mutex_unlock(&mdsc->mutex); | 1951 | mutex_unlock(&mdsc->mutex); |
1927 | goto out; | 1952 | goto out; |
1928 | } | 1953 | } |
@@ -2101,7 +2126,7 @@ static void handle_session(struct ceph_mds_session *session, | |||
2101 | pr_info("mds%d reconnect denied\n", session->s_mds); | 2126 | pr_info("mds%d reconnect denied\n", session->s_mds); |
2102 | remove_session_caps(session); | 2127 | remove_session_caps(session); |
2103 | wake = 1; /* for good measure */ | 2128 | wake = 1; /* for good measure */ |
2104 | complete(&mdsc->session_close_waiters); | 2129 | complete_all(&mdsc->session_close_waiters); |
2105 | kick_requests(mdsc, mds); | 2130 | kick_requests(mdsc, mds); |
2106 | break; | 2131 | break; |
2107 | 2132 | ||
@@ -2783,6 +2808,12 @@ void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc) | |||
2783 | drop_leases(mdsc); | 2808 | drop_leases(mdsc); |
2784 | ceph_flush_dirty_caps(mdsc); | 2809 | ceph_flush_dirty_caps(mdsc); |
2785 | wait_requests(mdsc); | 2810 | wait_requests(mdsc); |
2811 | |||
2812 | /* | ||
2813 | * wait for reply handlers to drop their request refs and | ||
2814 | * their inode/dcache refs | ||
2815 | */ | ||
2816 | ceph_msgr_flush(); | ||
2786 | } | 2817 | } |
2787 | 2818 | ||
2788 | /* | 2819 | /* |
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index b292fa42a66d..952410c60d09 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h | |||
@@ -188,6 +188,7 @@ struct ceph_mds_request { | |||
188 | int r_old_inode_drop, r_old_inode_unless; | 188 | int r_old_inode_drop, r_old_inode_unless; |
189 | 189 | ||
190 | struct ceph_msg *r_request; /* original request */ | 190 | struct ceph_msg *r_request; /* original request */ |
191 | int r_request_release_offset; | ||
191 | struct ceph_msg *r_reply; | 192 | struct ceph_msg *r_reply; |
192 | struct ceph_mds_reply_info_parsed r_reply_info; | 193 | struct ceph_mds_reply_info_parsed r_reply_info; |
193 | int r_err; | 194 | int r_err; |
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c index 64b8b1f7863d..15167b2daa55 100644 --- a/fs/ceph/messenger.c +++ b/fs/ceph/messenger.c | |||
@@ -43,7 +43,8 @@ static void ceph_fault(struct ceph_connection *con); | |||
43 | * nicely render a sockaddr as a string. | 43 | * nicely render a sockaddr as a string. |
44 | */ | 44 | */ |
45 | #define MAX_ADDR_STR 20 | 45 | #define MAX_ADDR_STR 20 |
46 | static char addr_str[MAX_ADDR_STR][40]; | 46 | #define MAX_ADDR_STR_LEN 60 |
47 | static char addr_str[MAX_ADDR_STR][MAX_ADDR_STR_LEN]; | ||
47 | static DEFINE_SPINLOCK(addr_str_lock); | 48 | static DEFINE_SPINLOCK(addr_str_lock); |
48 | static int last_addr_str; | 49 | static int last_addr_str; |
49 | 50 | ||
@@ -52,7 +53,6 @@ const char *pr_addr(const struct sockaddr_storage *ss) | |||
52 | int i; | 53 | int i; |
53 | char *s; | 54 | char *s; |
54 | struct sockaddr_in *in4 = (void *)ss; | 55 | struct sockaddr_in *in4 = (void *)ss; |
55 | unsigned char *quad = (void *)&in4->sin_addr.s_addr; | ||
56 | struct sockaddr_in6 *in6 = (void *)ss; | 56 | struct sockaddr_in6 *in6 = (void *)ss; |
57 | 57 | ||
58 | spin_lock(&addr_str_lock); | 58 | spin_lock(&addr_str_lock); |
@@ -64,25 +64,13 @@ const char *pr_addr(const struct sockaddr_storage *ss) | |||
64 | 64 | ||
65 | switch (ss->ss_family) { | 65 | switch (ss->ss_family) { |
66 | case AF_INET: | 66 | case AF_INET: |
67 | sprintf(s, "%u.%u.%u.%u:%u", | 67 | snprintf(s, MAX_ADDR_STR_LEN, "%pI4:%u", &in4->sin_addr, |
68 | (unsigned int)quad[0], | 68 | (unsigned int)ntohs(in4->sin_port)); |
69 | (unsigned int)quad[1], | ||
70 | (unsigned int)quad[2], | ||
71 | (unsigned int)quad[3], | ||
72 | (unsigned int)ntohs(in4->sin_port)); | ||
73 | break; | 69 | break; |
74 | 70 | ||
75 | case AF_INET6: | 71 | case AF_INET6: |
76 | sprintf(s, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x:%u", | 72 | snprintf(s, MAX_ADDR_STR_LEN, "[%pI6c]:%u", &in6->sin6_addr, |
77 | in6->sin6_addr.s6_addr16[0], | 73 | (unsigned int)ntohs(in6->sin6_port)); |
78 | in6->sin6_addr.s6_addr16[1], | ||
79 | in6->sin6_addr.s6_addr16[2], | ||
80 | in6->sin6_addr.s6_addr16[3], | ||
81 | in6->sin6_addr.s6_addr16[4], | ||
82 | in6->sin6_addr.s6_addr16[5], | ||
83 | in6->sin6_addr.s6_addr16[6], | ||
84 | in6->sin6_addr.s6_addr16[7], | ||
85 | (unsigned int)ntohs(in6->sin6_port)); | ||
86 | break; | 74 | break; |
87 | 75 | ||
88 | default: | 76 | default: |
@@ -215,12 +203,13 @@ static void set_sock_callbacks(struct socket *sock, | |||
215 | */ | 203 | */ |
216 | static struct socket *ceph_tcp_connect(struct ceph_connection *con) | 204 | static struct socket *ceph_tcp_connect(struct ceph_connection *con) |
217 | { | 205 | { |
218 | struct sockaddr *paddr = (struct sockaddr *)&con->peer_addr.in_addr; | 206 | struct sockaddr_storage *paddr = &con->peer_addr.in_addr; |
219 | struct socket *sock; | 207 | struct socket *sock; |
220 | int ret; | 208 | int ret; |
221 | 209 | ||
222 | BUG_ON(con->sock); | 210 | BUG_ON(con->sock); |
223 | ret = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); | 211 | ret = sock_create_kern(con->peer_addr.in_addr.ss_family, SOCK_STREAM, |
212 | IPPROTO_TCP, &sock); | ||
224 | if (ret) | 213 | if (ret) |
225 | return ERR_PTR(ret); | 214 | return ERR_PTR(ret); |
226 | con->sock = sock; | 215 | con->sock = sock; |
@@ -234,7 +223,8 @@ static struct socket *ceph_tcp_connect(struct ceph_connection *con) | |||
234 | 223 | ||
235 | dout("connect %s\n", pr_addr(&con->peer_addr.in_addr)); | 224 | dout("connect %s\n", pr_addr(&con->peer_addr.in_addr)); |
236 | 225 | ||
237 | ret = sock->ops->connect(sock, paddr, sizeof(*paddr), O_NONBLOCK); | 226 | ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr), |
227 | O_NONBLOCK); | ||
238 | if (ret == -EINPROGRESS) { | 228 | if (ret == -EINPROGRESS) { |
239 | dout("connect %s EINPROGRESS sk_state = %u\n", | 229 | dout("connect %s EINPROGRESS sk_state = %u\n", |
240 | pr_addr(&con->peer_addr.in_addr), | 230 | pr_addr(&con->peer_addr.in_addr), |
@@ -657,7 +647,7 @@ static void prepare_write_connect(struct ceph_messenger *msgr, | |||
657 | dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con, | 647 | dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con, |
658 | con->connect_seq, global_seq, proto); | 648 | con->connect_seq, global_seq, proto); |
659 | 649 | ||
660 | con->out_connect.features = CEPH_FEATURE_SUPPORTED_CLIENT; | 650 | con->out_connect.features = cpu_to_le64(CEPH_FEATURE_SUPPORTED_CLIENT); |
661 | con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT); | 651 | con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT); |
662 | con->out_connect.connect_seq = cpu_to_le32(con->connect_seq); | 652 | con->out_connect.connect_seq = cpu_to_le32(con->connect_seq); |
663 | con->out_connect.global_seq = cpu_to_le32(global_seq); | 653 | con->out_connect.global_seq = cpu_to_le32(global_seq); |
@@ -1009,19 +999,32 @@ int ceph_parse_ips(const char *c, const char *end, | |||
1009 | struct sockaddr_in *in4 = (void *)ss; | 999 | struct sockaddr_in *in4 = (void *)ss; |
1010 | struct sockaddr_in6 *in6 = (void *)ss; | 1000 | struct sockaddr_in6 *in6 = (void *)ss; |
1011 | int port; | 1001 | int port; |
1002 | char delim = ','; | ||
1003 | |||
1004 | if (*p == '[') { | ||
1005 | delim = ']'; | ||
1006 | p++; | ||
1007 | } | ||
1012 | 1008 | ||
1013 | memset(ss, 0, sizeof(*ss)); | 1009 | memset(ss, 0, sizeof(*ss)); |
1014 | if (in4_pton(p, end - p, (u8 *)&in4->sin_addr.s_addr, | 1010 | if (in4_pton(p, end - p, (u8 *)&in4->sin_addr.s_addr, |
1015 | ',', &ipend)) { | 1011 | delim, &ipend)) |
1016 | ss->ss_family = AF_INET; | 1012 | ss->ss_family = AF_INET; |
1017 | } else if (in6_pton(p, end - p, (u8 *)&in6->sin6_addr.s6_addr, | 1013 | else if (in6_pton(p, end - p, (u8 *)&in6->sin6_addr.s6_addr, |
1018 | ',', &ipend)) { | 1014 | delim, &ipend)) |
1019 | ss->ss_family = AF_INET6; | 1015 | ss->ss_family = AF_INET6; |
1020 | } else { | 1016 | else |
1021 | goto bad; | 1017 | goto bad; |
1022 | } | ||
1023 | p = ipend; | 1018 | p = ipend; |
1024 | 1019 | ||
1020 | if (delim == ']') { | ||
1021 | if (*p != ']') { | ||
1022 | dout("missing matching ']'\n"); | ||
1023 | goto bad; | ||
1024 | } | ||
1025 | p++; | ||
1026 | } | ||
1027 | |||
1025 | /* port? */ | 1028 | /* port? */ |
1026 | if (p < end && *p == ':') { | 1029 | if (p < end && *p == ':') { |
1027 | port = 0; | 1030 | port = 0; |
@@ -1055,7 +1058,7 @@ int ceph_parse_ips(const char *c, const char *end, | |||
1055 | return 0; | 1058 | return 0; |
1056 | 1059 | ||
1057 | bad: | 1060 | bad: |
1058 | pr_err("parse_ips bad ip '%s'\n", c); | 1061 | pr_err("parse_ips bad ip '%.*s'\n", (int)(end - c), c); |
1059 | return -EINVAL; | 1062 | return -EINVAL; |
1060 | } | 1063 | } |
1061 | 1064 | ||
@@ -1396,10 +1399,12 @@ static int read_partial_message(struct ceph_connection *con) | |||
1396 | if (!con->in_msg) { | 1399 | if (!con->in_msg) { |
1397 | dout("got hdr type %d front %d data %d\n", con->in_hdr.type, | 1400 | dout("got hdr type %d front %d data %d\n", con->in_hdr.type, |
1398 | con->in_hdr.front_len, con->in_hdr.data_len); | 1401 | con->in_hdr.front_len, con->in_hdr.data_len); |
1402 | skip = 0; | ||
1399 | con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip); | 1403 | con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip); |
1400 | if (skip) { | 1404 | if (skip) { |
1401 | /* skip this message */ | 1405 | /* skip this message */ |
1402 | dout("alloc_msg said skip message\n"); | 1406 | dout("alloc_msg said skip message\n"); |
1407 | BUG_ON(con->in_msg); | ||
1403 | con->in_base_pos = -front_len - middle_len - data_len - | 1408 | con->in_base_pos = -front_len - middle_len - data_len - |
1404 | sizeof(m->footer); | 1409 | sizeof(m->footer); |
1405 | con->in_tag = CEPH_MSGR_TAG_READY; | 1410 | con->in_tag = CEPH_MSGR_TAG_READY; |
@@ -2013,20 +2018,20 @@ void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) | |||
2013 | { | 2018 | { |
2014 | mutex_lock(&con->mutex); | 2019 | mutex_lock(&con->mutex); |
2015 | if (!list_empty(&msg->list_head)) { | 2020 | if (!list_empty(&msg->list_head)) { |
2016 | dout("con_revoke %p msg %p\n", con, msg); | 2021 | dout("con_revoke %p msg %p - was on queue\n", con, msg); |
2017 | list_del_init(&msg->list_head); | 2022 | list_del_init(&msg->list_head); |
2018 | ceph_msg_put(msg); | 2023 | ceph_msg_put(msg); |
2019 | msg->hdr.seq = 0; | 2024 | msg->hdr.seq = 0; |
2020 | if (con->out_msg == msg) { | 2025 | } |
2021 | ceph_msg_put(con->out_msg); | 2026 | if (con->out_msg == msg) { |
2022 | con->out_msg = NULL; | 2027 | dout("con_revoke %p msg %p - was sending\n", con, msg); |
2023 | } | 2028 | con->out_msg = NULL; |
2024 | if (con->out_kvec_is_msg) { | 2029 | if (con->out_kvec_is_msg) { |
2025 | con->out_skip = con->out_kvec_bytes; | 2030 | con->out_skip = con->out_kvec_bytes; |
2026 | con->out_kvec_is_msg = false; | 2031 | con->out_kvec_is_msg = false; |
2027 | } | 2032 | } |
2028 | } else { | 2033 | ceph_msg_put(msg); |
2029 | dout("con_revoke %p msg %p - not queued (sent?)\n", con, msg); | 2034 | msg->hdr.seq = 0; |
2030 | } | 2035 | } |
2031 | mutex_unlock(&con->mutex); | 2036 | mutex_unlock(&con->mutex); |
2032 | } | 2037 | } |
diff --git a/fs/ceph/mon_client.c b/fs/ceph/mon_client.c index 07a539906e67..54fe01c50706 100644 --- a/fs/ceph/mon_client.c +++ b/fs/ceph/mon_client.c | |||
@@ -345,7 +345,7 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, | |||
345 | 345 | ||
346 | out: | 346 | out: |
347 | mutex_unlock(&monc->mutex); | 347 | mutex_unlock(&monc->mutex); |
348 | wake_up(&client->auth_wq); | 348 | wake_up_all(&client->auth_wq); |
349 | } | 349 | } |
350 | 350 | ||
351 | /* | 351 | /* |
@@ -462,7 +462,7 @@ static void handle_statfs_reply(struct ceph_mon_client *monc, | |||
462 | } | 462 | } |
463 | mutex_unlock(&monc->mutex); | 463 | mutex_unlock(&monc->mutex); |
464 | if (req) { | 464 | if (req) { |
465 | complete(&req->completion); | 465 | complete_all(&req->completion); |
466 | put_generic_request(req); | 466 | put_generic_request(req); |
467 | } | 467 | } |
468 | return; | 468 | return; |
@@ -718,14 +718,15 @@ static void handle_auth_reply(struct ceph_mon_client *monc, | |||
718 | monc->m_auth->front_max); | 718 | monc->m_auth->front_max); |
719 | if (ret < 0) { | 719 | if (ret < 0) { |
720 | monc->client->auth_err = ret; | 720 | monc->client->auth_err = ret; |
721 | wake_up(&monc->client->auth_wq); | 721 | wake_up_all(&monc->client->auth_wq); |
722 | } else if (ret > 0) { | 722 | } else if (ret > 0) { |
723 | __send_prepared_auth_request(monc, ret); | 723 | __send_prepared_auth_request(monc, ret); |
724 | } else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) { | 724 | } else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) { |
725 | dout("authenticated, starting session\n"); | 725 | dout("authenticated, starting session\n"); |
726 | 726 | ||
727 | monc->client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT; | 727 | monc->client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT; |
728 | monc->client->msgr->inst.name.num = monc->auth->global_id; | 728 | monc->client->msgr->inst.name.num = |
729 | cpu_to_le64(monc->auth->global_id); | ||
729 | 730 | ||
730 | __send_subscribe(monc); | 731 | __send_subscribe(monc); |
731 | __resend_generic_request(monc); | 732 | __resend_generic_request(monc); |
diff --git a/fs/ceph/osd_client.c b/fs/ceph/osd_client.c index d25b4add85b4..e38522347898 100644 --- a/fs/ceph/osd_client.c +++ b/fs/ceph/osd_client.c | |||
@@ -862,12 +862,12 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, | |||
862 | if (req->r_callback) | 862 | if (req->r_callback) |
863 | req->r_callback(req, msg); | 863 | req->r_callback(req, msg); |
864 | else | 864 | else |
865 | complete(&req->r_completion); | 865 | complete_all(&req->r_completion); |
866 | 866 | ||
867 | if (flags & CEPH_OSD_FLAG_ONDISK) { | 867 | if (flags & CEPH_OSD_FLAG_ONDISK) { |
868 | if (req->r_safe_callback) | 868 | if (req->r_safe_callback) |
869 | req->r_safe_callback(req, msg); | 869 | req->r_safe_callback(req, msg); |
870 | complete(&req->r_safe_completion); /* fsync waiter */ | 870 | complete_all(&req->r_safe_completion); /* fsync waiter */ |
871 | } | 871 | } |
872 | 872 | ||
873 | done: | 873 | done: |
@@ -1083,7 +1083,7 @@ done: | |||
1083 | if (newmap) | 1083 | if (newmap) |
1084 | kick_requests(osdc, NULL); | 1084 | kick_requests(osdc, NULL); |
1085 | up_read(&osdc->map_sem); | 1085 | up_read(&osdc->map_sem); |
1086 | wake_up(&osdc->client->auth_wq); | 1086 | wake_up_all(&osdc->client->auth_wq); |
1087 | return; | 1087 | return; |
1088 | 1088 | ||
1089 | bad: | 1089 | bad: |
@@ -1344,7 +1344,7 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg) | |||
1344 | int type = le16_to_cpu(msg->hdr.type); | 1344 | int type = le16_to_cpu(msg->hdr.type); |
1345 | 1345 | ||
1346 | if (!osd) | 1346 | if (!osd) |
1347 | return; | 1347 | goto out; |
1348 | osdc = osd->o_osdc; | 1348 | osdc = osd->o_osdc; |
1349 | 1349 | ||
1350 | switch (type) { | 1350 | switch (type) { |
@@ -1359,6 +1359,7 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg) | |||
1359 | pr_err("received unknown message type %d %s\n", type, | 1359 | pr_err("received unknown message type %d %s\n", type, |
1360 | ceph_msg_type_name(type)); | 1360 | ceph_msg_type_name(type)); |
1361 | } | 1361 | } |
1362 | out: | ||
1362 | ceph_msg_put(msg); | 1363 | ceph_msg_put(msg); |
1363 | } | 1364 | } |
1364 | 1365 | ||
diff --git a/fs/ceph/osdmap.c b/fs/ceph/osdmap.c index ddc656fb5c05..416d46adbf87 100644 --- a/fs/ceph/osdmap.c +++ b/fs/ceph/osdmap.c | |||
@@ -568,6 +568,7 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) | |||
568 | if (ev > CEPH_PG_POOL_VERSION) { | 568 | if (ev > CEPH_PG_POOL_VERSION) { |
569 | pr_warning("got unknown v %d > %d of ceph_pg_pool\n", | 569 | pr_warning("got unknown v %d > %d of ceph_pg_pool\n", |
570 | ev, CEPH_PG_POOL_VERSION); | 570 | ev, CEPH_PG_POOL_VERSION); |
571 | kfree(pi); | ||
571 | goto bad; | 572 | goto bad; |
572 | } | 573 | } |
573 | __decode_pool(p, pi); | 574 | __decode_pool(p, pi); |
@@ -707,6 +708,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
707 | newcrush = crush_decode(*p, min(*p+len, end)); | 708 | newcrush = crush_decode(*p, min(*p+len, end)); |
708 | if (IS_ERR(newcrush)) | 709 | if (IS_ERR(newcrush)) |
709 | return ERR_CAST(newcrush); | 710 | return ERR_CAST(newcrush); |
711 | *p += len; | ||
710 | } | 712 | } |
711 | 713 | ||
712 | /* new flags? */ | 714 | /* new flags? */ |
@@ -829,12 +831,13 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
829 | /* remove any? */ | 831 | /* remove any? */ |
830 | while (rbp && pgid_cmp(rb_entry(rbp, struct ceph_pg_mapping, | 832 | while (rbp && pgid_cmp(rb_entry(rbp, struct ceph_pg_mapping, |
831 | node)->pgid, pgid) <= 0) { | 833 | node)->pgid, pgid) <= 0) { |
832 | struct rb_node *cur = rbp; | 834 | struct ceph_pg_mapping *cur = |
835 | rb_entry(rbp, struct ceph_pg_mapping, node); | ||
836 | |||
833 | rbp = rb_next(rbp); | 837 | rbp = rb_next(rbp); |
834 | dout(" removed pg_temp %llx\n", | 838 | dout(" removed pg_temp %llx\n", *(u64 *)&cur->pgid); |
835 | *(u64 *)&rb_entry(cur, struct ceph_pg_mapping, | 839 | rb_erase(&cur->node, &map->pg_temp); |
836 | node)->pgid); | 840 | kfree(cur); |
837 | rb_erase(cur, &map->pg_temp); | ||
838 | } | 841 | } |
839 | 842 | ||
840 | if (pglen) { | 843 | if (pglen) { |
@@ -850,19 +853,22 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
850 | for (j = 0; j < pglen; j++) | 853 | for (j = 0; j < pglen; j++) |
851 | pg->osds[j] = ceph_decode_32(p); | 854 | pg->osds[j] = ceph_decode_32(p); |
852 | err = __insert_pg_mapping(pg, &map->pg_temp); | 855 | err = __insert_pg_mapping(pg, &map->pg_temp); |
853 | if (err) | 856 | if (err) { |
857 | kfree(pg); | ||
854 | goto bad; | 858 | goto bad; |
859 | } | ||
855 | dout(" added pg_temp %llx len %d\n", *(u64 *)&pgid, | 860 | dout(" added pg_temp %llx len %d\n", *(u64 *)&pgid, |
856 | pglen); | 861 | pglen); |
857 | } | 862 | } |
858 | } | 863 | } |
859 | while (rbp) { | 864 | while (rbp) { |
860 | struct rb_node *cur = rbp; | 865 | struct ceph_pg_mapping *cur = |
866 | rb_entry(rbp, struct ceph_pg_mapping, node); | ||
867 | |||
861 | rbp = rb_next(rbp); | 868 | rbp = rb_next(rbp); |
862 | dout(" removed pg_temp %llx\n", | 869 | dout(" removed pg_temp %llx\n", *(u64 *)&cur->pgid); |
863 | *(u64 *)&rb_entry(cur, struct ceph_pg_mapping, | 870 | rb_erase(&cur->node, &map->pg_temp); |
864 | node)->pgid); | 871 | kfree(cur); |
865 | rb_erase(cur, &map->pg_temp); | ||
866 | } | 872 | } |
867 | 873 | ||
868 | /* ignore the rest */ | 874 | /* ignore the rest */ |
diff --git a/fs/char_dev.c b/fs/char_dev.c index d6db933df2b2..f80a4f25123c 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/cdev.h> | 20 | #include <linux/cdev.h> |
21 | #include <linux/mutex.h> | 21 | #include <linux/mutex.h> |
22 | #include <linux/backing-dev.h> | 22 | #include <linux/backing-dev.h> |
23 | #include <linux/tty.h> | ||
23 | 24 | ||
24 | #include "internal.h" | 25 | #include "internal.h" |
25 | 26 | ||
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 80f352596807..917b7d449bb2 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
@@ -2,7 +2,6 @@ config CIFS | |||
2 | tristate "CIFS support (advanced network filesystem, SMBFS successor)" | 2 | tristate "CIFS support (advanced network filesystem, SMBFS successor)" |
3 | depends on INET | 3 | depends on INET |
4 | select NLS | 4 | select NLS |
5 | select SLOW_WORK | ||
6 | help | 5 | help |
7 | This is the client VFS module for the Common Internet File System | 6 | This is the client VFS module for the Common Internet File System |
8 | (CIFS) protocol which is the successor to the Server Message Block | 7 | (CIFS) protocol which is the successor to the Server Message Block |
@@ -71,14 +70,14 @@ config CIFS_WEAK_PW_HASH | |||
71 | If unsure, say N. | 70 | If unsure, say N. |
72 | 71 | ||
73 | config CIFS_UPCALL | 72 | config CIFS_UPCALL |
74 | bool "Kerberos/SPNEGO advanced session setup" | 73 | bool "Kerberos/SPNEGO advanced session setup" |
75 | depends on CIFS && KEYS | 74 | depends on CIFS && KEYS |
76 | help | 75 | select DNS_RESOLVER |
77 | Enables an upcall mechanism for CIFS which accesses | 76 | help |
78 | userspace helper utilities to provide SPNEGO packaged (RFC 4178) | 77 | Enables an upcall mechanism for CIFS which accesses userspace helper |
79 | Kerberos tickets which are needed to mount to certain secure servers | 78 | utilities to provide SPNEGO packaged (RFC 4178) Kerberos tickets |
80 | (for which more secure Kerberos authentication is required). If | 79 | which are needed to mount to certain secure servers (for which more |
81 | unsure, say N. | 80 | secure Kerberos authentication is required). If unsure, say N. |
82 | 81 | ||
83 | config CIFS_XATTR | 82 | config CIFS_XATTR |
84 | bool "CIFS extended attributes" | 83 | bool "CIFS extended attributes" |
@@ -122,6 +121,7 @@ config CIFS_DEBUG2 | |||
122 | config CIFS_DFS_UPCALL | 121 | config CIFS_DFS_UPCALL |
123 | bool "DFS feature support" | 122 | bool "DFS feature support" |
124 | depends on CIFS && KEYS | 123 | depends on CIFS && KEYS |
124 | select DNS_RESOLVER | ||
125 | help | 125 | help |
126 | Distributed File System (DFS) support is used to access shares | 126 | Distributed File System (DFS) support is used to access shares |
127 | transparently in an enterprise name space, even if the share | 127 | transparently in an enterprise name space, even if the share |
@@ -131,6 +131,15 @@ config CIFS_DFS_UPCALL | |||
131 | IP addresses) which is needed for implicit mounts of DFS junction | 131 | IP addresses) which is needed for implicit mounts of DFS junction |
132 | points. If unsure, say N. | 132 | points. If unsure, say N. |
133 | 133 | ||
134 | config CIFS_FSCACHE | ||
135 | bool "Provide CIFS client caching support (EXPERIMENTAL)" | ||
136 | depends on EXPERIMENTAL | ||
137 | depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y | ||
138 | help | ||
139 | Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data | ||
140 | to be cached locally on disk through the general filesystem cache | ||
141 | manager. If unsure, say N. | ||
142 | |||
134 | config CIFS_EXPERIMENTAL | 143 | config CIFS_EXPERIMENTAL |
135 | bool "CIFS Experimental Features (EXPERIMENTAL)" | 144 | bool "CIFS Experimental Features (EXPERIMENTAL)" |
136 | depends on CIFS && EXPERIMENTAL | 145 | depends on CIFS && EXPERIMENTAL |
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 9948c0030e86..adefa60a9bdc 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile | |||
@@ -11,3 +11,5 @@ cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ | |||
11 | cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o | 11 | cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o |
12 | 12 | ||
13 | cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o | 13 | cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o |
14 | |||
15 | cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o | ||
diff --git a/fs/cifs/README b/fs/cifs/README index a727b7cb075f..a7081eeeb85d 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
@@ -568,8 +568,9 @@ module can be displayed via modinfo. | |||
568 | Misc /proc/fs/cifs Flags and Debug Info | 568 | Misc /proc/fs/cifs Flags and Debug Info |
569 | ======================================= | 569 | ======================================= |
570 | Informational pseudo-files: | 570 | Informational pseudo-files: |
571 | DebugData Displays information about active CIFS sessions | 571 | DebugData Displays information about active CIFS sessions and |
572 | and shares, as well as the cifs.ko version. | 572 | shares, features enabled as well as the cifs.ko |
573 | version. | ||
573 | Stats Lists summary resource usage information as well as per | 574 | Stats Lists summary resource usage information as well as per |
574 | share statistics, if CONFIG_CIFS_STATS in enabled | 575 | share statistics, if CONFIG_CIFS_STATS in enabled |
575 | in the kernel configuration. | 576 | in the kernel configuration. |
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c new file mode 100644 index 000000000000..224d7bbd1fcc --- /dev/null +++ b/fs/cifs/cache.c | |||
@@ -0,0 +1,331 @@ | |||
1 | /* | ||
2 | * fs/cifs/cache.c - CIFS filesystem cache index structure definitions | ||
3 | * | ||
4 | * Copyright (c) 2010 Novell, Inc. | ||
5 | * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as published | ||
9 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
15 | * the GNU Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public License | ||
18 | * along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | #include "fscache.h" | ||
22 | #include "cifs_debug.h" | ||
23 | |||
24 | /* | ||
25 | * CIFS filesystem definition for FS-Cache | ||
26 | */ | ||
27 | struct fscache_netfs cifs_fscache_netfs = { | ||
28 | .name = "cifs", | ||
29 | .version = 0, | ||
30 | }; | ||
31 | |||
32 | /* | ||
33 | * Register CIFS for caching with FS-Cache | ||
34 | */ | ||
35 | int cifs_fscache_register(void) | ||
36 | { | ||
37 | return fscache_register_netfs(&cifs_fscache_netfs); | ||
38 | } | ||
39 | |||
40 | /* | ||
41 | * Unregister CIFS for caching | ||
42 | */ | ||
43 | void cifs_fscache_unregister(void) | ||
44 | { | ||
45 | fscache_unregister_netfs(&cifs_fscache_netfs); | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * Key layout of CIFS server cache index object | ||
50 | */ | ||
51 | struct cifs_server_key { | ||
52 | uint16_t family; /* address family */ | ||
53 | uint16_t port; /* IP port */ | ||
54 | union { | ||
55 | struct in_addr ipv4_addr; | ||
56 | struct in6_addr ipv6_addr; | ||
57 | } addr[0]; | ||
58 | }; | ||
59 | |||
60 | /* | ||
61 | * Server object keyed by {IPaddress,port,family} tuple | ||
62 | */ | ||
63 | static uint16_t cifs_server_get_key(const void *cookie_netfs_data, | ||
64 | void *buffer, uint16_t maxbuf) | ||
65 | { | ||
66 | const struct TCP_Server_Info *server = cookie_netfs_data; | ||
67 | const struct sockaddr *sa = (struct sockaddr *) &server->addr.sockAddr; | ||
68 | struct cifs_server_key *key = buffer; | ||
69 | uint16_t key_len = sizeof(struct cifs_server_key); | ||
70 | |||
71 | memset(key, 0, key_len); | ||
72 | |||
73 | /* | ||
74 | * Should not be a problem as sin_family/sin6_family overlays | ||
75 | * sa_family field | ||
76 | */ | ||
77 | switch (sa->sa_family) { | ||
78 | case AF_INET: | ||
79 | key->family = server->addr.sockAddr.sin_family; | ||
80 | key->port = server->addr.sockAddr.sin_port; | ||
81 | key->addr[0].ipv4_addr = server->addr.sockAddr.sin_addr; | ||
82 | key_len += sizeof(key->addr[0].ipv4_addr); | ||
83 | break; | ||
84 | |||
85 | case AF_INET6: | ||
86 | key->family = server->addr.sockAddr6.sin6_family; | ||
87 | key->port = server->addr.sockAddr6.sin6_port; | ||
88 | key->addr[0].ipv6_addr = server->addr.sockAddr6.sin6_addr; | ||
89 | key_len += sizeof(key->addr[0].ipv6_addr); | ||
90 | break; | ||
91 | |||
92 | default: | ||
93 | cERROR(1, "CIFS: Unknown network family '%d'", sa->sa_family); | ||
94 | key_len = 0; | ||
95 | break; | ||
96 | } | ||
97 | |||
98 | return key_len; | ||
99 | } | ||
100 | |||
101 | /* | ||
102 | * Server object for FS-Cache | ||
103 | */ | ||
104 | const struct fscache_cookie_def cifs_fscache_server_index_def = { | ||
105 | .name = "CIFS.server", | ||
106 | .type = FSCACHE_COOKIE_TYPE_INDEX, | ||
107 | .get_key = cifs_server_get_key, | ||
108 | }; | ||
109 | |||
110 | /* | ||
111 | * Auxiliary data attached to CIFS superblock within the cache | ||
112 | */ | ||
113 | struct cifs_fscache_super_auxdata { | ||
114 | u64 resource_id; /* unique server resource id */ | ||
115 | }; | ||
116 | |||
117 | static char *extract_sharename(const char *treename) | ||
118 | { | ||
119 | const char *src; | ||
120 | char *delim, *dst; | ||
121 | int len; | ||
122 | |||
123 | /* skip double chars at the beginning */ | ||
124 | src = treename + 2; | ||
125 | |||
126 | /* share name is always preceded by '\\' now */ | ||
127 | delim = strchr(src, '\\'); | ||
128 | if (!delim) | ||
129 | return ERR_PTR(-EINVAL); | ||
130 | delim++; | ||
131 | len = strlen(delim); | ||
132 | |||
133 | /* caller has to free the memory */ | ||
134 | dst = kstrndup(delim, len, GFP_KERNEL); | ||
135 | if (!dst) | ||
136 | return ERR_PTR(-ENOMEM); | ||
137 | |||
138 | return dst; | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * Superblock object currently keyed by share name | ||
143 | */ | ||
144 | static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer, | ||
145 | uint16_t maxbuf) | ||
146 | { | ||
147 | const struct cifsTconInfo *tcon = cookie_netfs_data; | ||
148 | char *sharename; | ||
149 | uint16_t len; | ||
150 | |||
151 | sharename = extract_sharename(tcon->treeName); | ||
152 | if (IS_ERR(sharename)) { | ||
153 | cFYI(1, "CIFS: couldn't extract sharename\n"); | ||
154 | sharename = NULL; | ||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | len = strlen(sharename); | ||
159 | if (len > maxbuf) | ||
160 | return 0; | ||
161 | |||
162 | memcpy(buffer, sharename, len); | ||
163 | |||
164 | kfree(sharename); | ||
165 | |||
166 | return len; | ||
167 | } | ||
168 | |||
169 | static uint16_t | ||
170 | cifs_fscache_super_get_aux(const void *cookie_netfs_data, void *buffer, | ||
171 | uint16_t maxbuf) | ||
172 | { | ||
173 | struct cifs_fscache_super_auxdata auxdata; | ||
174 | const struct cifsTconInfo *tcon = cookie_netfs_data; | ||
175 | |||
176 | memset(&auxdata, 0, sizeof(auxdata)); | ||
177 | auxdata.resource_id = tcon->resource_id; | ||
178 | |||
179 | if (maxbuf > sizeof(auxdata)) | ||
180 | maxbuf = sizeof(auxdata); | ||
181 | |||
182 | memcpy(buffer, &auxdata, maxbuf); | ||
183 | |||
184 | return maxbuf; | ||
185 | } | ||
186 | |||
187 | static enum | ||
188 | fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data, | ||
189 | const void *data, | ||
190 | uint16_t datalen) | ||
191 | { | ||
192 | struct cifs_fscache_super_auxdata auxdata; | ||
193 | const struct cifsTconInfo *tcon = cookie_netfs_data; | ||
194 | |||
195 | if (datalen != sizeof(auxdata)) | ||
196 | return FSCACHE_CHECKAUX_OBSOLETE; | ||
197 | |||
198 | memset(&auxdata, 0, sizeof(auxdata)); | ||
199 | auxdata.resource_id = tcon->resource_id; | ||
200 | |||
201 | if (memcmp(data, &auxdata, datalen) != 0) | ||
202 | return FSCACHE_CHECKAUX_OBSOLETE; | ||
203 | |||
204 | return FSCACHE_CHECKAUX_OKAY; | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * Superblock object for FS-Cache | ||
209 | */ | ||
210 | const struct fscache_cookie_def cifs_fscache_super_index_def = { | ||
211 | .name = "CIFS.super", | ||
212 | .type = FSCACHE_COOKIE_TYPE_INDEX, | ||
213 | .get_key = cifs_super_get_key, | ||
214 | .get_aux = cifs_fscache_super_get_aux, | ||
215 | .check_aux = cifs_fscache_super_check_aux, | ||
216 | }; | ||
217 | |||
218 | /* | ||
219 | * Auxiliary data attached to CIFS inode within the cache | ||
220 | */ | ||
221 | struct cifs_fscache_inode_auxdata { | ||
222 | struct timespec last_write_time; | ||
223 | struct timespec last_change_time; | ||
224 | u64 eof; | ||
225 | }; | ||
226 | |||
227 | static uint16_t cifs_fscache_inode_get_key(const void *cookie_netfs_data, | ||
228 | void *buffer, uint16_t maxbuf) | ||
229 | { | ||
230 | const struct cifsInodeInfo *cifsi = cookie_netfs_data; | ||
231 | uint16_t keylen; | ||
232 | |||
233 | /* use the UniqueId as the key */ | ||
234 | keylen = sizeof(cifsi->uniqueid); | ||
235 | if (keylen > maxbuf) | ||
236 | keylen = 0; | ||
237 | else | ||
238 | memcpy(buffer, &cifsi->uniqueid, keylen); | ||
239 | |||
240 | return keylen; | ||
241 | } | ||
242 | |||
243 | static void | ||
244 | cifs_fscache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size) | ||
245 | { | ||
246 | const struct cifsInodeInfo *cifsi = cookie_netfs_data; | ||
247 | |||
248 | *size = cifsi->vfs_inode.i_size; | ||
249 | } | ||
250 | |||
251 | static uint16_t | ||
252 | cifs_fscache_inode_get_aux(const void *cookie_netfs_data, void *buffer, | ||
253 | uint16_t maxbuf) | ||
254 | { | ||
255 | struct cifs_fscache_inode_auxdata auxdata; | ||
256 | const struct cifsInodeInfo *cifsi = cookie_netfs_data; | ||
257 | |||
258 | memset(&auxdata, 0, sizeof(auxdata)); | ||
259 | auxdata.eof = cifsi->server_eof; | ||
260 | auxdata.last_write_time = cifsi->vfs_inode.i_mtime; | ||
261 | auxdata.last_change_time = cifsi->vfs_inode.i_ctime; | ||
262 | |||
263 | if (maxbuf > sizeof(auxdata)) | ||
264 | maxbuf = sizeof(auxdata); | ||
265 | |||
266 | memcpy(buffer, &auxdata, maxbuf); | ||
267 | |||
268 | return maxbuf; | ||
269 | } | ||
270 | |||
271 | static enum | ||
272 | fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data, | ||
273 | const void *data, | ||
274 | uint16_t datalen) | ||
275 | { | ||
276 | struct cifs_fscache_inode_auxdata auxdata; | ||
277 | struct cifsInodeInfo *cifsi = cookie_netfs_data; | ||
278 | |||
279 | if (datalen != sizeof(auxdata)) | ||
280 | return FSCACHE_CHECKAUX_OBSOLETE; | ||
281 | |||
282 | memset(&auxdata, 0, sizeof(auxdata)); | ||
283 | auxdata.eof = cifsi->server_eof; | ||
284 | auxdata.last_write_time = cifsi->vfs_inode.i_mtime; | ||
285 | auxdata.last_change_time = cifsi->vfs_inode.i_ctime; | ||
286 | |||
287 | if (memcmp(data, &auxdata, datalen) != 0) | ||
288 | return FSCACHE_CHECKAUX_OBSOLETE; | ||
289 | |||
290 | return FSCACHE_CHECKAUX_OKAY; | ||
291 | } | ||
292 | |||
293 | static void cifs_fscache_inode_now_uncached(void *cookie_netfs_data) | ||
294 | { | ||
295 | struct cifsInodeInfo *cifsi = cookie_netfs_data; | ||
296 | struct pagevec pvec; | ||
297 | pgoff_t first; | ||
298 | int loop, nr_pages; | ||
299 | |||
300 | pagevec_init(&pvec, 0); | ||
301 | first = 0; | ||
302 | |||
303 | cFYI(1, "cifs inode 0x%p now uncached", cifsi); | ||
304 | |||
305 | for (;;) { | ||
306 | nr_pages = pagevec_lookup(&pvec, | ||
307 | cifsi->vfs_inode.i_mapping, first, | ||
308 | PAGEVEC_SIZE - pagevec_count(&pvec)); | ||
309 | if (!nr_pages) | ||
310 | break; | ||
311 | |||
312 | for (loop = 0; loop < nr_pages; loop++) | ||
313 | ClearPageFsCache(pvec.pages[loop]); | ||
314 | |||
315 | first = pvec.pages[nr_pages - 1]->index + 1; | ||
316 | |||
317 | pvec.nr = nr_pages; | ||
318 | pagevec_release(&pvec); | ||
319 | cond_resched(); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | const struct fscache_cookie_def cifs_fscache_inode_object_def = { | ||
324 | .name = "CIFS.uniqueid", | ||
325 | .type = FSCACHE_COOKIE_TYPE_DATAFILE, | ||
326 | .get_key = cifs_fscache_inode_get_key, | ||
327 | .get_attr = cifs_fscache_inode_get_attr, | ||
328 | .get_aux = cifs_fscache_inode_get_aux, | ||
329 | .check_aux = cifs_fscache_inode_check_aux, | ||
330 | .now_uncached = cifs_fscache_inode_now_uncached, | ||
331 | }; | ||
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 4fce6e61b34e..eb1ba493489f 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
@@ -119,6 +119,31 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | |||
119 | "Display Internal CIFS Data Structures for Debugging\n" | 119 | "Display Internal CIFS Data Structures for Debugging\n" |
120 | "---------------------------------------------------\n"); | 120 | "---------------------------------------------------\n"); |
121 | seq_printf(m, "CIFS Version %s\n", CIFS_VERSION); | 121 | seq_printf(m, "CIFS Version %s\n", CIFS_VERSION); |
122 | seq_printf(m, "Features: "); | ||
123 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
124 | seq_printf(m, "dfs"); | ||
125 | seq_putc(m, ' '); | ||
126 | #endif | ||
127 | #ifdef CONFIG_CIFS_FSCACHE | ||
128 | seq_printf(m, "fscache"); | ||
129 | seq_putc(m, ' '); | ||
130 | #endif | ||
131 | #ifdef CONFIG_CIFS_WEAK_PW_HASH | ||
132 | seq_printf(m, "lanman"); | ||
133 | seq_putc(m, ' '); | ||
134 | #endif | ||
135 | #ifdef CONFIG_CIFS_POSIX | ||
136 | seq_printf(m, "posix"); | ||
137 | seq_putc(m, ' '); | ||
138 | #endif | ||
139 | #ifdef CONFIG_CIFS_UPCALL | ||
140 | seq_printf(m, "spnego"); | ||
141 | seq_putc(m, ' '); | ||
142 | #endif | ||
143 | #ifdef CONFIG_CIFS_XATTR | ||
144 | seq_printf(m, "xattr"); | ||
145 | #endif | ||
146 | seq_putc(m, '\n'); | ||
122 | seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid); | 147 | seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid); |
123 | seq_printf(m, "Servers:"); | 148 | seq_printf(m, "Servers:"); |
124 | 149 | ||
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index ac19a6f3dae0..d6ced7aa23cf 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c | |||
@@ -141,7 +141,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata, | |||
141 | } | 141 | } |
142 | 142 | ||
143 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); | 143 | rc = dns_resolve_server_name_to_ip(*devname, &srvIP); |
144 | if (rc != 0) { | 144 | if (rc < 0) { |
145 | cERROR(1, "%s: Failed to resolve server part of %s to IP: %d", | 145 | cERROR(1, "%s: Failed to resolve server part of %s to IP: %d", |
146 | __func__, *devname, rc); | 146 | __func__, *devname, rc); |
147 | goto compose_mount_options_err; | 147 | goto compose_mount_options_err; |
@@ -150,8 +150,7 @@ char *cifs_compose_mount_options(const char *sb_mountdata, | |||
150 | * assuming that we have 'unc=' and 'ip=' in | 150 | * assuming that we have 'unc=' and 'ip=' in |
151 | * the original sb_mountdata | 151 | * the original sb_mountdata |
152 | */ | 152 | */ |
153 | md_len = strlen(sb_mountdata) + strlen(srvIP) + | 153 | md_len = strlen(sb_mountdata) + rc + strlen(ref->node_name) + 12; |
154 | strlen(ref->node_name) + 12; | ||
155 | mountdata = kzalloc(md_len+1, GFP_KERNEL); | 154 | mountdata = kzalloc(md_len+1, GFP_KERNEL); |
156 | if (mountdata == NULL) { | 155 | if (mountdata == NULL) { |
157 | rc = -ENOMEM; | 156 | rc = -ENOMEM; |
@@ -230,28 +229,22 @@ compose_mount_options_err: | |||
230 | goto compose_mount_options_out; | 229 | goto compose_mount_options_out; |
231 | } | 230 | } |
232 | 231 | ||
233 | 232 | /** | |
234 | static struct vfsmount *cifs_dfs_do_refmount(const struct vfsmount *mnt_parent, | 233 | * cifs_dfs_do_refmount - mounts specified path using provided refferal |
235 | struct dentry *dentry, const struct dfs_info3_param *ref) | 234 | * @cifs_sb: parent/root superblock |
235 | * @fullpath: full path in UNC format | ||
236 | * @ref: server's referral | ||
237 | */ | ||
238 | static struct vfsmount *cifs_dfs_do_refmount(struct cifs_sb_info *cifs_sb, | ||
239 | const char *fullpath, const struct dfs_info3_param *ref) | ||
236 | { | 240 | { |
237 | struct cifs_sb_info *cifs_sb; | ||
238 | struct vfsmount *mnt; | 241 | struct vfsmount *mnt; |
239 | char *mountdata; | 242 | char *mountdata; |
240 | char *devname = NULL; | 243 | char *devname = NULL; |
241 | char *fullpath; | ||
242 | |||
243 | cifs_sb = CIFS_SB(dentry->d_inode->i_sb); | ||
244 | /* | ||
245 | * this function gives us a path with a double backslash prefix. We | ||
246 | * require a single backslash for DFS. | ||
247 | */ | ||
248 | fullpath = build_path_from_dentry(dentry); | ||
249 | if (!fullpath) | ||
250 | return ERR_PTR(-ENOMEM); | ||
251 | 244 | ||
245 | /* strip first '\' from fullpath */ | ||
252 | mountdata = cifs_compose_mount_options(cifs_sb->mountdata, | 246 | mountdata = cifs_compose_mount_options(cifs_sb->mountdata, |
253 | fullpath + 1, ref, &devname); | 247 | fullpath + 1, ref, &devname); |
254 | kfree(fullpath); | ||
255 | 248 | ||
256 | if (IS_ERR(mountdata)) | 249 | if (IS_ERR(mountdata)) |
257 | return (struct vfsmount *)mountdata; | 250 | return (struct vfsmount *)mountdata; |
@@ -357,8 +350,8 @@ cifs_dfs_follow_mountpoint(struct dentry *dentry, struct nameidata *nd) | |||
357 | rc = -EINVAL; | 350 | rc = -EINVAL; |
358 | goto out_err; | 351 | goto out_err; |
359 | } | 352 | } |
360 | mnt = cifs_dfs_do_refmount(nd->path.mnt, | 353 | mnt = cifs_dfs_do_refmount(cifs_sb, |
361 | nd->path.dentry, referrals + i); | 354 | full_path, referrals + i); |
362 | cFYI(1, "%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__, | 355 | cFYI(1, "%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__, |
363 | referrals[i].node_name, mnt); | 356 | referrals[i].node_name, mnt); |
364 | 357 | ||
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 246a167cb913..9e771450c3b8 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
@@ -35,6 +35,7 @@ | |||
35 | #define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */ | 35 | #define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */ |
36 | #define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */ | 36 | #define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */ |
37 | #define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/ | 37 | #define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/ |
38 | #define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */ | ||
38 | 39 | ||
39 | struct cifs_sb_info { | 40 | struct cifs_sb_info { |
40 | struct cifsTconInfo *tcon; /* primary mount */ | 41 | struct cifsTconInfo *tcon; /* primary mount */ |
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 379bd7d9c05f..87044906cd1f 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
@@ -84,6 +84,9 @@ struct key_type cifs_spnego_key_type = { | |||
84 | /* strlen of ";uid=0x" */ | 84 | /* strlen of ";uid=0x" */ |
85 | #define UID_KEY_LEN 7 | 85 | #define UID_KEY_LEN 7 |
86 | 86 | ||
87 | /* strlen of ";creduid=0x" */ | ||
88 | #define CREDUID_KEY_LEN 11 | ||
89 | |||
87 | /* strlen of ";user=" */ | 90 | /* strlen of ";user=" */ |
88 | #define USER_KEY_LEN 6 | 91 | #define USER_KEY_LEN 6 |
89 | 92 | ||
@@ -107,6 +110,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | |||
107 | IP_KEY_LEN + INET6_ADDRSTRLEN + | 110 | IP_KEY_LEN + INET6_ADDRSTRLEN + |
108 | MAX_MECH_STR_LEN + | 111 | MAX_MECH_STR_LEN + |
109 | UID_KEY_LEN + (sizeof(uid_t) * 2) + | 112 | UID_KEY_LEN + (sizeof(uid_t) * 2) + |
113 | CREDUID_KEY_LEN + (sizeof(uid_t) * 2) + | ||
110 | USER_KEY_LEN + strlen(sesInfo->userName) + | 114 | USER_KEY_LEN + strlen(sesInfo->userName) + |
111 | PID_KEY_LEN + (sizeof(pid_t) * 2) + 1; | 115 | PID_KEY_LEN + (sizeof(pid_t) * 2) + 1; |
112 | 116 | ||
@@ -144,6 +148,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) | |||
144 | sprintf(dp, ";uid=0x%x", sesInfo->linux_uid); | 148 | sprintf(dp, ";uid=0x%x", sesInfo->linux_uid); |
145 | 149 | ||
146 | dp = description + strlen(description); | 150 | dp = description + strlen(description); |
151 | sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid); | ||
152 | |||
153 | dp = description + strlen(description); | ||
147 | sprintf(dp, ";user=%s", sesInfo->userName); | 154 | sprintf(dp, ";user=%s", sesInfo->userName); |
148 | 155 | ||
149 | dp = description + strlen(description); | 156 | dp = description + strlen(description); |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 484e52bb40bb..a5ed10c9afef 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -45,8 +45,8 @@ | |||
45 | #include "cifs_fs_sb.h" | 45 | #include "cifs_fs_sb.h" |
46 | #include <linux/mm.h> | 46 | #include <linux/mm.h> |
47 | #include <linux/key-type.h> | 47 | #include <linux/key-type.h> |
48 | #include "dns_resolve.h" | ||
49 | #include "cifs_spnego.h" | 48 | #include "cifs_spnego.h" |
49 | #include "fscache.h" | ||
50 | #define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ | 50 | #define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ |
51 | 51 | ||
52 | int cifsFYI = 0; | 52 | int cifsFYI = 0; |
@@ -329,6 +329,12 @@ cifs_destroy_inode(struct inode *inode) | |||
329 | } | 329 | } |
330 | 330 | ||
331 | static void | 331 | static void |
332 | cifs_clear_inode(struct inode *inode) | ||
333 | { | ||
334 | cifs_fscache_release_inode_cookie(inode); | ||
335 | } | ||
336 | |||
337 | static void | ||
332 | cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) | 338 | cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) |
333 | { | 339 | { |
334 | seq_printf(s, ",addr="); | 340 | seq_printf(s, ",addr="); |
@@ -489,6 +495,7 @@ static const struct super_operations cifs_super_ops = { | |||
489 | .alloc_inode = cifs_alloc_inode, | 495 | .alloc_inode = cifs_alloc_inode, |
490 | .destroy_inode = cifs_destroy_inode, | 496 | .destroy_inode = cifs_destroy_inode, |
491 | .drop_inode = cifs_drop_inode, | 497 | .drop_inode = cifs_drop_inode, |
498 | .clear_inode = cifs_clear_inode, | ||
492 | /* .delete_inode = cifs_delete_inode, */ /* Do not need above | 499 | /* .delete_inode = cifs_delete_inode, */ /* Do not need above |
493 | function unless later we add lazy close of inodes or unless the | 500 | function unless later we add lazy close of inodes or unless the |
494 | kernel forgets to call us with the same number of releases (closes) | 501 | kernel forgets to call us with the same number of releases (closes) |
@@ -902,6 +909,10 @@ init_cifs(void) | |||
902 | cFYI(1, "cifs_max_pending set to max of 256"); | 909 | cFYI(1, "cifs_max_pending set to max of 256"); |
903 | } | 910 | } |
904 | 911 | ||
912 | rc = cifs_fscache_register(); | ||
913 | if (rc) | ||
914 | goto out; | ||
915 | |||
905 | rc = cifs_init_inodecache(); | 916 | rc = cifs_init_inodecache(); |
906 | if (rc) | 917 | if (rc) |
907 | goto out_clean_proc; | 918 | goto out_clean_proc; |
@@ -922,27 +933,13 @@ init_cifs(void) | |||
922 | if (rc) | 933 | if (rc) |
923 | goto out_unregister_filesystem; | 934 | goto out_unregister_filesystem; |
924 | #endif | 935 | #endif |
925 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
926 | rc = register_key_type(&key_type_dns_resolver); | ||
927 | if (rc) | ||
928 | goto out_unregister_key_type; | ||
929 | #endif | ||
930 | rc = slow_work_register_user(THIS_MODULE); | ||
931 | if (rc) | ||
932 | goto out_unregister_resolver_key; | ||
933 | 936 | ||
934 | return 0; | 937 | return 0; |
935 | 938 | ||
936 | out_unregister_resolver_key: | ||
937 | #ifdef CONFIG_CIFS_DFS_UPCALL | ||
938 | unregister_key_type(&key_type_dns_resolver); | ||
939 | out_unregister_key_type: | ||
940 | #endif | ||
941 | #ifdef CONFIG_CIFS_UPCALL | 939 | #ifdef CONFIG_CIFS_UPCALL |
942 | unregister_key_type(&cifs_spnego_key_type); | ||
943 | out_unregister_filesystem: | 940 | out_unregister_filesystem: |
944 | #endif | ||
945 | unregister_filesystem(&cifs_fs_type); | 941 | unregister_filesystem(&cifs_fs_type); |
942 | #endif | ||
946 | out_destroy_request_bufs: | 943 | out_destroy_request_bufs: |
947 | cifs_destroy_request_bufs(); | 944 | cifs_destroy_request_bufs(); |
948 | out_destroy_mids: | 945 | out_destroy_mids: |
@@ -951,6 +948,8 @@ init_cifs(void) | |||
951 | cifs_destroy_inodecache(); | 948 | cifs_destroy_inodecache(); |
952 | out_clean_proc: | 949 | out_clean_proc: |
953 | cifs_proc_clean(); | 950 | cifs_proc_clean(); |
951 | cifs_fscache_unregister(); | ||
952 | out: | ||
954 | return rc; | 953 | return rc; |
955 | } | 954 | } |
956 | 955 | ||
@@ -959,9 +958,9 @@ exit_cifs(void) | |||
959 | { | 958 | { |
960 | cFYI(DBG2, "exit_cifs"); | 959 | cFYI(DBG2, "exit_cifs"); |
961 | cifs_proc_clean(); | 960 | cifs_proc_clean(); |
961 | cifs_fscache_unregister(); | ||
962 | #ifdef CONFIG_CIFS_DFS_UPCALL | 962 | #ifdef CONFIG_CIFS_DFS_UPCALL |
963 | cifs_dfs_release_automount_timer(); | 963 | cifs_dfs_release_automount_timer(); |
964 | unregister_key_type(&key_type_dns_resolver); | ||
965 | #endif | 964 | #endif |
966 | #ifdef CONFIG_CIFS_UPCALL | 965 | #ifdef CONFIG_CIFS_UPCALL |
967 | unregister_key_type(&cifs_spnego_key_type); | 966 | unregister_key_type(&cifs_spnego_key_type); |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index a7eb65c84b1c..d82f5fb4761e 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -114,5 +114,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
114 | extern const struct export_operations cifs_export_ops; | 114 | extern const struct export_operations cifs_export_ops; |
115 | #endif /* EXPERIMENTAL */ | 115 | #endif /* EXPERIMENTAL */ |
116 | 116 | ||
117 | #define CIFS_VERSION "1.64" | 117 | #define CIFS_VERSION "1.65" |
118 | #endif /* _CIFSFS_H */ | 118 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index a88479ceaad5..0cdfb8c32ac6 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -16,10 +16,13 @@ | |||
16 | * the GNU Lesser General Public License for more details. | 16 | * the GNU Lesser General Public License for more details. |
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | #ifndef _CIFS_GLOB_H | ||
20 | #define _CIFS_GLOB_H | ||
21 | |||
19 | #include <linux/in.h> | 22 | #include <linux/in.h> |
20 | #include <linux/in6.h> | 23 | #include <linux/in6.h> |
21 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
22 | #include <linux/slow-work.h> | 25 | #include <linux/workqueue.h> |
23 | #include "cifs_fs_sb.h" | 26 | #include "cifs_fs_sb.h" |
24 | #include "cifsacl.h" | 27 | #include "cifsacl.h" |
25 | /* | 28 | /* |
@@ -34,7 +37,7 @@ | |||
34 | #define MAX_SHARE_SIZE 64 /* used to be 20, this should still be enough */ | 37 | #define MAX_SHARE_SIZE 64 /* used to be 20, this should still be enough */ |
35 | #define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null | 38 | #define MAX_USERNAME_SIZE 32 /* 32 is to allow for 15 char names + null |
36 | termination then *2 for unicode versions */ | 39 | termination then *2 for unicode versions */ |
37 | #define MAX_PASSWORD_SIZE 16 | 40 | #define MAX_PASSWORD_SIZE 512 /* max for windows seems to be 256 wide chars */ |
38 | 41 | ||
39 | #define CIFS_MIN_RCV_POOL 4 | 42 | #define CIFS_MIN_RCV_POOL 4 |
40 | 43 | ||
@@ -80,8 +83,7 @@ enum statusEnum { | |||
80 | }; | 83 | }; |
81 | 84 | ||
82 | enum securityEnum { | 85 | enum securityEnum { |
83 | PLAINTXT = 0, /* Legacy with Plaintext passwords */ | 86 | LANMAN = 0, /* Legacy LANMAN auth */ |
84 | LANMAN, /* Legacy LANMAN auth */ | ||
85 | NTLM, /* Legacy NTLM012 auth with NTLM hash */ | 87 | NTLM, /* Legacy NTLM012 auth with NTLM hash */ |
86 | NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ | 88 | NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ |
87 | RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ | 89 | RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ |
@@ -142,7 +144,6 @@ struct TCP_Server_Info { | |||
142 | struct list_head pending_mid_q; | 144 | struct list_head pending_mid_q; |
143 | void *Server_NlsInfo; /* BB - placeholder for future NLS info */ | 145 | void *Server_NlsInfo; /* BB - placeholder for future NLS info */ |
144 | unsigned short server_codepage; /* codepage for the server */ | 146 | unsigned short server_codepage; /* codepage for the server */ |
145 | unsigned long ip_address; /* IP addr for the server if known */ | ||
146 | enum protocolEnum protocolType; | 147 | enum protocolEnum protocolType; |
147 | char versionMajor; | 148 | char versionMajor; |
148 | char versionMinor; | 149 | char versionMinor; |
@@ -190,19 +191,9 @@ struct TCP_Server_Info { | |||
190 | bool sec_mskerberos; /* supports legacy MS Kerberos */ | 191 | bool sec_mskerberos; /* supports legacy MS Kerberos */ |
191 | bool sec_kerberosu2u; /* supports U2U Kerberos */ | 192 | bool sec_kerberosu2u; /* supports U2U Kerberos */ |
192 | bool sec_ntlmssp; /* supports NTLMSSP */ | 193 | bool sec_ntlmssp; /* supports NTLMSSP */ |
193 | }; | 194 | #ifdef CONFIG_CIFS_FSCACHE |
194 | 195 | struct fscache_cookie *fscache; /* client index cache cookie */ | |
195 | /* | 196 | #endif |
196 | * The following is our shortcut to user information. We surface the uid, | ||
197 | * and name. We always get the password on the fly in case it | ||
198 | * has changed. We also hang a list of sessions owned by this user off here. | ||
199 | */ | ||
200 | struct cifsUidInfo { | ||
201 | struct list_head userList; | ||
202 | struct list_head sessionList; /* SMB sessions for this user */ | ||
203 | uid_t linux_uid; | ||
204 | char user[MAX_USERNAME_SIZE + 1]; /* ascii name of user */ | ||
205 | /* BB may need ptr or callback for PAM or WinBind info */ | ||
206 | }; | 197 | }; |
207 | 198 | ||
208 | /* | 199 | /* |
@@ -212,9 +203,6 @@ struct cifsSesInfo { | |||
212 | struct list_head smb_ses_list; | 203 | struct list_head smb_ses_list; |
213 | struct list_head tcon_list; | 204 | struct list_head tcon_list; |
214 | struct mutex session_mutex; | 205 | struct mutex session_mutex; |
215 | #if 0 | ||
216 | struct cifsUidInfo *uidInfo; /* pointer to user info */ | ||
217 | #endif | ||
218 | struct TCP_Server_Info *server; /* pointer to server info */ | 206 | struct TCP_Server_Info *server; /* pointer to server info */ |
219 | int ses_count; /* reference counter */ | 207 | int ses_count; /* reference counter */ |
220 | enum statusEnum status; | 208 | enum statusEnum status; |
@@ -226,7 +214,8 @@ struct cifsSesInfo { | |||
226 | char *serverNOS; /* name of network operating system of server */ | 214 | char *serverNOS; /* name of network operating system of server */ |
227 | char *serverDomain; /* security realm of server */ | 215 | char *serverDomain; /* security realm of server */ |
228 | int Suid; /* remote smb uid */ | 216 | int Suid; /* remote smb uid */ |
229 | uid_t linux_uid; /* local Linux uid */ | 217 | uid_t linux_uid; /* overriding owner of files on the mount */ |
218 | uid_t cred_uid; /* owner of credentials */ | ||
230 | int capabilities; | 219 | int capabilities; |
231 | char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for | 220 | char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for |
232 | TCP names - will ipv6 and sctp addresses fit? */ | 221 | TCP names - will ipv6 and sctp addresses fit? */ |
@@ -311,6 +300,10 @@ struct cifsTconInfo { | |||
311 | bool local_lease:1; /* check leases (only) on local system not remote */ | 300 | bool local_lease:1; /* check leases (only) on local system not remote */ |
312 | bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ | 301 | bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */ |
313 | bool need_reconnect:1; /* connection reset, tid now invalid */ | 302 | bool need_reconnect:1; /* connection reset, tid now invalid */ |
303 | #ifdef CONFIG_CIFS_FSCACHE | ||
304 | u64 resource_id; /* server resource id */ | ||
305 | struct fscache_cookie *fscache; /* cookie for share */ | ||
306 | #endif | ||
314 | /* BB add field for back pointer to sb struct(s)? */ | 307 | /* BB add field for back pointer to sb struct(s)? */ |
315 | }; | 308 | }; |
316 | 309 | ||
@@ -363,7 +356,7 @@ struct cifsFileInfo { | |||
363 | atomic_t count; /* reference count */ | 356 | atomic_t count; /* reference count */ |
364 | struct mutex fh_mutex; /* prevents reopen race after dead ses*/ | 357 | struct mutex fh_mutex; /* prevents reopen race after dead ses*/ |
365 | struct cifs_search_info srch_inf; | 358 | struct cifs_search_info srch_inf; |
366 | struct slow_work oplock_break; /* slow_work job for oplock breaks */ | 359 | struct work_struct oplock_break; /* work for oplock breaks */ |
367 | }; | 360 | }; |
368 | 361 | ||
369 | /* Take a reference on the file private data */ | 362 | /* Take a reference on the file private data */ |
@@ -398,6 +391,9 @@ struct cifsInodeInfo { | |||
398 | bool invalid_mapping:1; /* pagecache is invalid */ | 391 | bool invalid_mapping:1; /* pagecache is invalid */ |
399 | u64 server_eof; /* current file size on server */ | 392 | u64 server_eof; /* current file size on server */ |
400 | u64 uniqueid; /* server inode number */ | 393 | u64 uniqueid; /* server inode number */ |
394 | #ifdef CONFIG_CIFS_FSCACHE | ||
395 | struct fscache_cookie *fscache; | ||
396 | #endif | ||
401 | struct inode vfs_inode; | 397 | struct inode vfs_inode; |
402 | }; | 398 | }; |
403 | 399 | ||
@@ -732,4 +728,10 @@ GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ | |||
732 | GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ | 728 | GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ |
733 | GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ | 729 | GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ |
734 | 730 | ||
731 | void cifs_oplock_break(struct work_struct *work); | ||
732 | void cifs_oplock_break_get(struct cifsFileInfo *cfile); | ||
733 | void cifs_oplock_break_put(struct cifsFileInfo *cfile); | ||
734 | |||
735 | extern const struct slow_work_ops cifs_oplock_break_ops; | 735 | extern const struct slow_work_ops cifs_oplock_break_ops; |
736 | |||
737 | #endif /* _CIFS_GLOB_H */ | ||
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index fb6318b81509..1f5450814087 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -86,7 +86,9 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr); | |||
86 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | 86 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); |
87 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 87 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
88 | struct TCP_Server_Info *server); | 88 | struct TCP_Server_Info *server); |
89 | extern int cifs_convert_address(char *src, void *dst); | 89 | extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); |
90 | extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | ||
91 | unsigned short int port); | ||
90 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); | 92 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); |
91 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 93 | extern void header_assemble(struct smb_hdr *, char /* command */ , |
92 | const struct cifsTconInfo *, int /* length of | 94 | const struct cifsTconInfo *, int /* length of |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2208f06e4c45..95c2ea67edfb 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include "nterr.h" | 48 | #include "nterr.h" |
49 | #include "rfc1002pdu.h" | 49 | #include "rfc1002pdu.h" |
50 | #include "cn_cifs.h" | 50 | #include "cn_cifs.h" |
51 | #include "fscache.h" | ||
51 | 52 | ||
52 | #define CIFS_PORT 445 | 53 | #define CIFS_PORT 445 |
53 | #define RFC1001_PORT 139 | 54 | #define RFC1001_PORT 139 |
@@ -66,6 +67,7 @@ struct smb_vol { | |||
66 | char *iocharset; /* local code page for mapping to and from Unicode */ | 67 | char *iocharset; /* local code page for mapping to and from Unicode */ |
67 | char source_rfc1001_name[16]; /* netbios name of client */ | 68 | char source_rfc1001_name[16]; /* netbios name of client */ |
68 | char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ | 69 | char target_rfc1001_name[16]; /* netbios name of server for Win9x/ME */ |
70 | uid_t cred_uid; | ||
69 | uid_t linux_uid; | 71 | uid_t linux_uid; |
70 | gid_t linux_gid; | 72 | gid_t linux_gid; |
71 | mode_t file_mode; | 73 | mode_t file_mode; |
@@ -97,6 +99,7 @@ struct smb_vol { | |||
97 | bool noblocksnd:1; | 99 | bool noblocksnd:1; |
98 | bool noautotune:1; | 100 | bool noautotune:1; |
99 | bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ | 101 | bool nostrictsync:1; /* do not force expensive SMBflush on every sync */ |
102 | bool fsc:1; /* enable fscache */ | ||
100 | unsigned int rsize; | 103 | unsigned int rsize; |
101 | unsigned int wsize; | 104 | unsigned int wsize; |
102 | bool sockopt_tcp_nodelay:1; | 105 | bool sockopt_tcp_nodelay:1; |
@@ -830,7 +833,8 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
830 | /* null target name indicates to use *SMBSERVR default called name | 833 | /* null target name indicates to use *SMBSERVR default called name |
831 | if we end up sending RFC1001 session initialize */ | 834 | if we end up sending RFC1001 session initialize */ |
832 | vol->target_rfc1001_name[0] = 0; | 835 | vol->target_rfc1001_name[0] = 0; |
833 | vol->linux_uid = current_uid(); /* use current_euid() instead? */ | 836 | vol->cred_uid = current_uid(); |
837 | vol->linux_uid = current_uid(); | ||
834 | vol->linux_gid = current_gid(); | 838 | vol->linux_gid = current_gid(); |
835 | 839 | ||
836 | /* default to only allowing write access to owner of the mount */ | 840 | /* default to only allowing write access to owner of the mount */ |
@@ -1257,6 +1261,12 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1257 | } else if ((strnicmp(data, "nocase", 6) == 0) || | 1261 | } else if ((strnicmp(data, "nocase", 6) == 0) || |
1258 | (strnicmp(data, "ignorecase", 10) == 0)) { | 1262 | (strnicmp(data, "ignorecase", 10) == 0)) { |
1259 | vol->nocase = 1; | 1263 | vol->nocase = 1; |
1264 | } else if (strnicmp(data, "mand", 4) == 0) { | ||
1265 | /* ignore */ | ||
1266 | } else if (strnicmp(data, "nomand", 6) == 0) { | ||
1267 | /* ignore */ | ||
1268 | } else if (strnicmp(data, "_netdev", 7) == 0) { | ||
1269 | /* ignore */ | ||
1260 | } else if (strnicmp(data, "brl", 3) == 0) { | 1270 | } else if (strnicmp(data, "brl", 3) == 0) { |
1261 | vol->nobrl = 0; | 1271 | vol->nobrl = 0; |
1262 | } else if ((strnicmp(data, "nobrl", 5) == 0) || | 1272 | } else if ((strnicmp(data, "nobrl", 5) == 0) || |
@@ -1331,6 +1341,8 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1331 | printk(KERN_WARNING "CIFS: Mount option noac not " | 1341 | printk(KERN_WARNING "CIFS: Mount option noac not " |
1332 | "supported. Instead set " | 1342 | "supported. Instead set " |
1333 | "/proc/fs/cifs/LookupCacheEnabled to 0\n"); | 1343 | "/proc/fs/cifs/LookupCacheEnabled to 0\n"); |
1344 | } else if (strnicmp(data, "fsc", 3) == 0) { | ||
1345 | vol->fsc = true; | ||
1334 | } else | 1346 | } else |
1335 | printk(KERN_WARNING "CIFS: Unknown mount option %s\n", | 1347 | printk(KERN_WARNING "CIFS: Unknown mount option %s\n", |
1336 | data); | 1348 | data); |
@@ -1380,18 +1392,92 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
1380 | return 0; | 1392 | return 0; |
1381 | } | 1393 | } |
1382 | 1394 | ||
1395 | static bool | ||
1396 | match_address(struct TCP_Server_Info *server, struct sockaddr *addr) | ||
1397 | { | ||
1398 | struct sockaddr_in *addr4 = (struct sockaddr_in *)addr; | ||
1399 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; | ||
1400 | |||
1401 | switch (addr->sa_family) { | ||
1402 | case AF_INET: | ||
1403 | if (addr4->sin_addr.s_addr != | ||
1404 | server->addr.sockAddr.sin_addr.s_addr) | ||
1405 | return false; | ||
1406 | if (addr4->sin_port && | ||
1407 | addr4->sin_port != server->addr.sockAddr.sin_port) | ||
1408 | return false; | ||
1409 | break; | ||
1410 | case AF_INET6: | ||
1411 | if (!ipv6_addr_equal(&addr6->sin6_addr, | ||
1412 | &server->addr.sockAddr6.sin6_addr)) | ||
1413 | return false; | ||
1414 | if (addr6->sin6_scope_id != | ||
1415 | server->addr.sockAddr6.sin6_scope_id) | ||
1416 | return false; | ||
1417 | if (addr6->sin6_port && | ||
1418 | addr6->sin6_port != server->addr.sockAddr6.sin6_port) | ||
1419 | return false; | ||
1420 | break; | ||
1421 | } | ||
1422 | |||
1423 | return true; | ||
1424 | } | ||
1425 | |||
1426 | static bool | ||
1427 | match_security(struct TCP_Server_Info *server, struct smb_vol *vol) | ||
1428 | { | ||
1429 | unsigned int secFlags; | ||
1430 | |||
1431 | if (vol->secFlg & (~(CIFSSEC_MUST_SIGN | CIFSSEC_MUST_SEAL))) | ||
1432 | secFlags = vol->secFlg; | ||
1433 | else | ||
1434 | secFlags = global_secflags | vol->secFlg; | ||
1435 | |||
1436 | switch (server->secType) { | ||
1437 | case LANMAN: | ||
1438 | if (!(secFlags & (CIFSSEC_MAY_LANMAN|CIFSSEC_MAY_PLNTXT))) | ||
1439 | return false; | ||
1440 | break; | ||
1441 | case NTLMv2: | ||
1442 | if (!(secFlags & CIFSSEC_MAY_NTLMV2)) | ||
1443 | return false; | ||
1444 | break; | ||
1445 | case NTLM: | ||
1446 | if (!(secFlags & CIFSSEC_MAY_NTLM)) | ||
1447 | return false; | ||
1448 | break; | ||
1449 | case Kerberos: | ||
1450 | if (!(secFlags & CIFSSEC_MAY_KRB5)) | ||
1451 | return false; | ||
1452 | break; | ||
1453 | case RawNTLMSSP: | ||
1454 | if (!(secFlags & CIFSSEC_MAY_NTLMSSP)) | ||
1455 | return false; | ||
1456 | break; | ||
1457 | default: | ||
1458 | /* shouldn't happen */ | ||
1459 | return false; | ||
1460 | } | ||
1461 | |||
1462 | /* now check if signing mode is acceptible */ | ||
1463 | if ((secFlags & CIFSSEC_MAY_SIGN) == 0 && | ||
1464 | (server->secMode & SECMODE_SIGN_REQUIRED)) | ||
1465 | return false; | ||
1466 | else if (((secFlags & CIFSSEC_MUST_SIGN) == CIFSSEC_MUST_SIGN) && | ||
1467 | (server->secMode & | ||
1468 | (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)) == 0) | ||
1469 | return false; | ||
1470 | |||
1471 | return true; | ||
1472 | } | ||
1473 | |||
1383 | static struct TCP_Server_Info * | 1474 | static struct TCP_Server_Info * |
1384 | cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port) | 1475 | cifs_find_tcp_session(struct sockaddr *addr, struct smb_vol *vol) |
1385 | { | 1476 | { |
1386 | struct list_head *tmp; | ||
1387 | struct TCP_Server_Info *server; | 1477 | struct TCP_Server_Info *server; |
1388 | struct sockaddr_in *addr4 = (struct sockaddr_in *) addr; | ||
1389 | struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) addr; | ||
1390 | 1478 | ||
1391 | write_lock(&cifs_tcp_ses_lock); | 1479 | write_lock(&cifs_tcp_ses_lock); |
1392 | list_for_each(tmp, &cifs_tcp_ses_list) { | 1480 | list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { |
1393 | server = list_entry(tmp, struct TCP_Server_Info, | ||
1394 | tcp_ses_list); | ||
1395 | /* | 1481 | /* |
1396 | * the demux thread can exit on its own while still in CifsNew | 1482 | * the demux thread can exit on its own while still in CifsNew |
1397 | * so don't accept any sockets in that state. Since the | 1483 | * so don't accept any sockets in that state. Since the |
@@ -1401,37 +1487,11 @@ cifs_find_tcp_session(struct sockaddr_storage *addr, unsigned short int port) | |||
1401 | if (server->tcpStatus == CifsNew) | 1487 | if (server->tcpStatus == CifsNew) |
1402 | continue; | 1488 | continue; |
1403 | 1489 | ||
1404 | switch (addr->ss_family) { | 1490 | if (!match_address(server, addr)) |
1405 | case AF_INET: | 1491 | continue; |
1406 | if (addr4->sin_addr.s_addr == | ||
1407 | server->addr.sockAddr.sin_addr.s_addr) { | ||
1408 | addr4->sin_port = htons(port); | ||
1409 | /* user overrode default port? */ | ||
1410 | if (addr4->sin_port) { | ||
1411 | if (addr4->sin_port != | ||
1412 | server->addr.sockAddr.sin_port) | ||
1413 | continue; | ||
1414 | } | ||
1415 | break; | ||
1416 | } else | ||
1417 | continue; | ||
1418 | 1492 | ||
1419 | case AF_INET6: | 1493 | if (!match_security(server, vol)) |
1420 | if (ipv6_addr_equal(&addr6->sin6_addr, | 1494 | continue; |
1421 | &server->addr.sockAddr6.sin6_addr) && | ||
1422 | (addr6->sin6_scope_id == | ||
1423 | server->addr.sockAddr6.sin6_scope_id)) { | ||
1424 | addr6->sin6_port = htons(port); | ||
1425 | /* user overrode default port? */ | ||
1426 | if (addr6->sin6_port) { | ||
1427 | if (addr6->sin6_port != | ||
1428 | server->addr.sockAddr6.sin6_port) | ||
1429 | continue; | ||
1430 | } | ||
1431 | break; | ||
1432 | } else | ||
1433 | continue; | ||
1434 | } | ||
1435 | 1495 | ||
1436 | ++server->srv_count; | 1496 | ++server->srv_count; |
1437 | write_unlock(&cifs_tcp_ses_lock); | 1497 | write_unlock(&cifs_tcp_ses_lock); |
@@ -1460,6 +1520,8 @@ cifs_put_tcp_session(struct TCP_Server_Info *server) | |||
1460 | server->tcpStatus = CifsExiting; | 1520 | server->tcpStatus = CifsExiting; |
1461 | spin_unlock(&GlobalMid_Lock); | 1521 | spin_unlock(&GlobalMid_Lock); |
1462 | 1522 | ||
1523 | cifs_fscache_release_client_cookie(server); | ||
1524 | |||
1463 | task = xchg(&server->tsk, NULL); | 1525 | task = xchg(&server->tsk, NULL); |
1464 | if (task) | 1526 | if (task) |
1465 | force_sig(SIGKILL, task); | 1527 | force_sig(SIGKILL, task); |
@@ -1479,7 +1541,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1479 | cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip); | 1541 | cFYI(1, "UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip); |
1480 | 1542 | ||
1481 | if (volume_info->UNCip && volume_info->UNC) { | 1543 | if (volume_info->UNCip && volume_info->UNC) { |
1482 | rc = cifs_convert_address(volume_info->UNCip, &addr); | 1544 | rc = cifs_fill_sockaddr((struct sockaddr *)&addr, |
1545 | volume_info->UNCip, | ||
1546 | strlen(volume_info->UNCip), | ||
1547 | volume_info->port); | ||
1483 | if (!rc) { | 1548 | if (!rc) { |
1484 | /* we failed translating address */ | 1549 | /* we failed translating address */ |
1485 | rc = -EINVAL; | 1550 | rc = -EINVAL; |
@@ -1499,7 +1564,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1499 | } | 1564 | } |
1500 | 1565 | ||
1501 | /* see if we already have a matching tcp_ses */ | 1566 | /* see if we already have a matching tcp_ses */ |
1502 | tcp_ses = cifs_find_tcp_session(&addr, volume_info->port); | 1567 | tcp_ses = cifs_find_tcp_session((struct sockaddr *)&addr, volume_info); |
1503 | if (tcp_ses) | 1568 | if (tcp_ses) |
1504 | return tcp_ses; | 1569 | return tcp_ses; |
1505 | 1570 | ||
@@ -1543,12 +1608,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1543 | cFYI(1, "attempting ipv6 connect"); | 1608 | cFYI(1, "attempting ipv6 connect"); |
1544 | /* BB should we allow ipv6 on port 139? */ | 1609 | /* BB should we allow ipv6 on port 139? */ |
1545 | /* other OS never observed in Wild doing 139 with v6 */ | 1610 | /* other OS never observed in Wild doing 139 with v6 */ |
1546 | sin_server6->sin6_port = htons(volume_info->port); | ||
1547 | memcpy(&tcp_ses->addr.sockAddr6, sin_server6, | 1611 | memcpy(&tcp_ses->addr.sockAddr6, sin_server6, |
1548 | sizeof(struct sockaddr_in6)); | 1612 | sizeof(struct sockaddr_in6)); |
1549 | rc = ipv6_connect(tcp_ses); | 1613 | rc = ipv6_connect(tcp_ses); |
1550 | } else { | 1614 | } else { |
1551 | sin_server->sin_port = htons(volume_info->port); | ||
1552 | memcpy(&tcp_ses->addr.sockAddr, sin_server, | 1615 | memcpy(&tcp_ses->addr.sockAddr, sin_server, |
1553 | sizeof(struct sockaddr_in)); | 1616 | sizeof(struct sockaddr_in)); |
1554 | rc = ipv4_connect(tcp_ses); | 1617 | rc = ipv4_connect(tcp_ses); |
@@ -1577,6 +1640,8 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
1577 | list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); | 1640 | list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); |
1578 | write_unlock(&cifs_tcp_ses_lock); | 1641 | write_unlock(&cifs_tcp_ses_lock); |
1579 | 1642 | ||
1643 | cifs_fscache_get_client_cookie(tcp_ses); | ||
1644 | |||
1580 | return tcp_ses; | 1645 | return tcp_ses; |
1581 | 1646 | ||
1582 | out_err: | 1647 | out_err: |
@@ -1591,17 +1656,27 @@ out_err: | |||
1591 | } | 1656 | } |
1592 | 1657 | ||
1593 | static struct cifsSesInfo * | 1658 | static struct cifsSesInfo * |
1594 | cifs_find_smb_ses(struct TCP_Server_Info *server, char *username) | 1659 | cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol) |
1595 | { | 1660 | { |
1596 | struct list_head *tmp; | ||
1597 | struct cifsSesInfo *ses; | 1661 | struct cifsSesInfo *ses; |
1598 | 1662 | ||
1599 | write_lock(&cifs_tcp_ses_lock); | 1663 | write_lock(&cifs_tcp_ses_lock); |
1600 | list_for_each(tmp, &server->smb_ses_list) { | 1664 | list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { |
1601 | ses = list_entry(tmp, struct cifsSesInfo, smb_ses_list); | 1665 | switch (server->secType) { |
1602 | if (strncmp(ses->userName, username, MAX_USERNAME_SIZE)) | 1666 | case Kerberos: |
1603 | continue; | 1667 | if (vol->cred_uid != ses->cred_uid) |
1604 | 1668 | continue; | |
1669 | break; | ||
1670 | default: | ||
1671 | /* anything else takes username/password */ | ||
1672 | if (strncmp(ses->userName, vol->username, | ||
1673 | MAX_USERNAME_SIZE)) | ||
1674 | continue; | ||
1675 | if (strlen(vol->username) != 0 && | ||
1676 | strncmp(ses->password, vol->password, | ||
1677 | MAX_PASSWORD_SIZE)) | ||
1678 | continue; | ||
1679 | } | ||
1605 | ++ses->ses_count; | 1680 | ++ses->ses_count; |
1606 | write_unlock(&cifs_tcp_ses_lock); | 1681 | write_unlock(&cifs_tcp_ses_lock); |
1607 | return ses; | 1682 | return ses; |
@@ -1643,7 +1718,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
1643 | 1718 | ||
1644 | xid = GetXid(); | 1719 | xid = GetXid(); |
1645 | 1720 | ||
1646 | ses = cifs_find_smb_ses(server, volume_info->username); | 1721 | ses = cifs_find_smb_ses(server, volume_info); |
1647 | if (ses) { | 1722 | if (ses) { |
1648 | cFYI(1, "Existing smb sess found (status=%d)", ses->status); | 1723 | cFYI(1, "Existing smb sess found (status=%d)", ses->status); |
1649 | 1724 | ||
@@ -1706,6 +1781,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) | |||
1706 | if (ses->domainName) | 1781 | if (ses->domainName) |
1707 | strcpy(ses->domainName, volume_info->domainname); | 1782 | strcpy(ses->domainName, volume_info->domainname); |
1708 | } | 1783 | } |
1784 | ses->cred_uid = volume_info->cred_uid; | ||
1709 | ses->linux_uid = volume_info->linux_uid; | 1785 | ses->linux_uid = volume_info->linux_uid; |
1710 | ses->overrideSecFlg = volume_info->secFlg; | 1786 | ses->overrideSecFlg = volume_info->secFlg; |
1711 | 1787 | ||
@@ -1773,6 +1849,7 @@ cifs_put_tcon(struct cifsTconInfo *tcon) | |||
1773 | CIFSSMBTDis(xid, tcon); | 1849 | CIFSSMBTDis(xid, tcon); |
1774 | _FreeXid(xid); | 1850 | _FreeXid(xid); |
1775 | 1851 | ||
1852 | cifs_fscache_release_super_cookie(tcon); | ||
1776 | tconInfoFree(tcon); | 1853 | tconInfoFree(tcon); |
1777 | cifs_put_smb_ses(ses); | 1854 | cifs_put_smb_ses(ses); |
1778 | } | 1855 | } |
@@ -1843,6 +1920,8 @@ cifs_get_tcon(struct cifsSesInfo *ses, struct smb_vol *volume_info) | |||
1843 | list_add(&tcon->tcon_list, &ses->tcon_list); | 1920 | list_add(&tcon->tcon_list, &ses->tcon_list); |
1844 | write_unlock(&cifs_tcp_ses_lock); | 1921 | write_unlock(&cifs_tcp_ses_lock); |
1845 | 1922 | ||
1923 | cifs_fscache_get_super_cookie(tcon); | ||
1924 | |||
1846 | return tcon; | 1925 | return tcon; |
1847 | 1926 | ||
1848 | out_fail: | 1927 | out_fail: |
@@ -2397,6 +2476,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, | |||
2397 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; | 2476 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID; |
2398 | if (pvolume_info->dynperm) | 2477 | if (pvolume_info->dynperm) |
2399 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; | 2478 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM; |
2479 | if (pvolume_info->fsc) | ||
2480 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE; | ||
2400 | if (pvolume_info->direct_io) { | 2481 | if (pvolume_info->direct_io) { |
2401 | cFYI(1, "mounting share using direct i/o"); | 2482 | cFYI(1, "mounting share using direct i/o"); |
2402 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; | 2483 | cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e7ae78b66fa1..578d88c5b46e 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -130,12 +130,6 @@ cifs_bp_rename_retry: | |||
130 | return full_path; | 130 | return full_path; |
131 | } | 131 | } |
132 | 132 | ||
133 | /* | ||
134 | * When called with struct file pointer set to NULL, there is no way we could | ||
135 | * update file->private_data, but getting it stuck on openFileList provides a | ||
136 | * way to access it from cifs_fill_filedata and thereby set file->private_data | ||
137 | * from cifs_open. | ||
138 | */ | ||
139 | struct cifsFileInfo * | 133 | struct cifsFileInfo * |
140 | cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, | 134 | cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, |
141 | struct file *file, struct vfsmount *mnt, unsigned int oflags) | 135 | struct file *file, struct vfsmount *mnt, unsigned int oflags) |
@@ -163,7 +157,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, | |||
163 | mutex_init(&pCifsFile->lock_mutex); | 157 | mutex_init(&pCifsFile->lock_mutex); |
164 | INIT_LIST_HEAD(&pCifsFile->llist); | 158 | INIT_LIST_HEAD(&pCifsFile->llist); |
165 | atomic_set(&pCifsFile->count, 1); | 159 | atomic_set(&pCifsFile->count, 1); |
166 | slow_work_init(&pCifsFile->oplock_break, &cifs_oplock_break_ops); | 160 | INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); |
167 | 161 | ||
168 | write_lock(&GlobalSMBSeslock); | 162 | write_lock(&GlobalSMBSeslock); |
169 | list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList); | 163 | list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList); |
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 4db2c5e7283f..0eb87026cad3 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c | |||
@@ -4,6 +4,8 @@ | |||
4 | * Copyright (c) 2007 Igor Mammedov | 4 | * Copyright (c) 2007 Igor Mammedov |
5 | * Author(s): Igor Mammedov (niallain@gmail.com) | 5 | * Author(s): Igor Mammedov (niallain@gmail.com) |
6 | * Steve French (sfrench@us.ibm.com) | 6 | * Steve French (sfrench@us.ibm.com) |
7 | * Wang Lei (wang840925@gmail.com) | ||
8 | * David Howells (dhowells@redhat.com) | ||
7 | * | 9 | * |
8 | * Contains the CIFS DFS upcall routines used for hostname to | 10 | * Contains the CIFS DFS upcall routines used for hostname to |
9 | * IP address translation. | 11 | * IP address translation. |
@@ -24,145 +26,73 @@ | |||
24 | */ | 26 | */ |
25 | 27 | ||
26 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
27 | #include <keys/user-type.h> | 29 | #include <linux/dns_resolver.h> |
28 | #include "dns_resolve.h" | 30 | #include "dns_resolve.h" |
29 | #include "cifsglob.h" | 31 | #include "cifsglob.h" |
30 | #include "cifsproto.h" | 32 | #include "cifsproto.h" |
31 | #include "cifs_debug.h" | 33 | #include "cifs_debug.h" |
32 | 34 | ||
33 | /* Checks if supplied name is IP address | 35 | /** |
34 | * returns: | 36 | * dns_resolve_server_name_to_ip - Resolve UNC server name to ip address. |
35 | * 1 - name is IP | 37 | * @unc: UNC path specifying the server |
36 | * 0 - name is not IP | 38 | * @ip_addr: Where to return the IP address. |
37 | */ | 39 | * |
38 | static int | 40 | * The IP address will be returned in string form, and the caller is |
39 | is_ip(char *name) | 41 | * responsible for freeing it. |
40 | { | 42 | * |
41 | struct sockaddr_storage ss; | 43 | * Returns length of result on success, -ve on error. |
42 | |||
43 | return cifs_convert_address(name, &ss); | ||
44 | } | ||
45 | |||
46 | static int | ||
47 | dns_resolver_instantiate(struct key *key, const void *data, | ||
48 | size_t datalen) | ||
49 | { | ||
50 | int rc = 0; | ||
51 | char *ip; | ||
52 | |||
53 | ip = kmalloc(datalen + 1, GFP_KERNEL); | ||
54 | if (!ip) | ||
55 | return -ENOMEM; | ||
56 | |||
57 | memcpy(ip, data, datalen); | ||
58 | ip[datalen] = '\0'; | ||
59 | |||
60 | /* make sure this looks like an address */ | ||
61 | if (!is_ip(ip)) { | ||
62 | kfree(ip); | ||
63 | return -EINVAL; | ||
64 | } | ||
65 | |||
66 | key->type_data.x[0] = datalen; | ||
67 | key->payload.data = ip; | ||
68 | |||
69 | return rc; | ||
70 | } | ||
71 | |||
72 | static void | ||
73 | dns_resolver_destroy(struct key *key) | ||
74 | { | ||
75 | kfree(key->payload.data); | ||
76 | } | ||
77 | |||
78 | struct key_type key_type_dns_resolver = { | ||
79 | .name = "dns_resolver", | ||
80 | .def_datalen = sizeof(struct in_addr), | ||
81 | .describe = user_describe, | ||
82 | .instantiate = dns_resolver_instantiate, | ||
83 | .destroy = dns_resolver_destroy, | ||
84 | .match = user_match, | ||
85 | }; | ||
86 | |||
87 | /* Resolves server name to ip address. | ||
88 | * input: | ||
89 | * unc - server UNC | ||
90 | * output: | ||
91 | * *ip_addr - pointer to server ip, caller responcible for freeing it. | ||
92 | * return 0 on success | ||
93 | */ | 44 | */ |
94 | int | 45 | int |
95 | dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) | 46 | dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) |
96 | { | 47 | { |
97 | int rc = -EAGAIN; | 48 | struct sockaddr_storage ss; |
98 | struct key *rkey = ERR_PTR(-EAGAIN); | 49 | const char *hostname, *sep; |
99 | char *name; | 50 | char *name; |
100 | char *data = NULL; | 51 | int len, rc; |
101 | int len; | ||
102 | 52 | ||
103 | if (!ip_addr || !unc) | 53 | if (!ip_addr || !unc) |
104 | return -EINVAL; | 54 | return -EINVAL; |
105 | 55 | ||
106 | /* search for server name delimiter */ | ||
107 | len = strlen(unc); | 56 | len = strlen(unc); |
108 | if (len < 3) { | 57 | if (len < 3) { |
109 | cFYI(1, "%s: unc is too short: %s", __func__, unc); | 58 | cFYI(1, "%s: unc is too short: %s", __func__, unc); |
110 | return -EINVAL; | 59 | return -EINVAL; |
111 | } | 60 | } |
61 | |||
62 | /* Discount leading slashes for cifs */ | ||
112 | len -= 2; | 63 | len -= 2; |
113 | name = memchr(unc+2, '\\', len); | 64 | hostname = unc + 2; |
114 | if (!name) { | 65 | |
66 | /* Search for server name delimiter */ | ||
67 | sep = memchr(hostname, '\\', len); | ||
68 | if (sep) | ||
69 | len = sep - unc; | ||
70 | else | ||
115 | cFYI(1, "%s: probably server name is whole unc: %s", | 71 | cFYI(1, "%s: probably server name is whole unc: %s", |
116 | __func__, unc); | 72 | __func__, unc); |
117 | } else { | 73 | |
118 | len = (name - unc) - 2/* leading // */; | 74 | /* Try to interpret hostname as an IPv4 or IPv6 address */ |
119 | } | 75 | rc = cifs_convert_address((struct sockaddr *)&ss, hostname, len); |
76 | if (rc > 0) | ||
77 | goto name_is_IP_address; | ||
78 | |||
79 | /* Perform the upcall */ | ||
80 | rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL); | ||
81 | if (rc < 0) | ||
82 | cERROR(1, "%s: unable to resolve: %*.*s", | ||
83 | __func__, len, len, hostname); | ||
84 | else | ||
85 | cFYI(1, "%s: resolved: %*.*s to %s", | ||
86 | __func__, len, len, hostname, *ip_addr); | ||
87 | return rc; | ||
120 | 88 | ||
121 | name = kmalloc(len+1, GFP_KERNEL); | 89 | name_is_IP_address: |
122 | if (!name) { | 90 | name = kmalloc(len + 1, GFP_KERNEL); |
123 | rc = -ENOMEM; | 91 | if (!name) |
124 | return rc; | 92 | return -ENOMEM; |
125 | } | 93 | memcpy(name, hostname, len); |
126 | memcpy(name, unc+2, len); | ||
127 | name[len] = 0; | 94 | name[len] = 0; |
128 | 95 | cFYI(1, "%s: unc is IP, skipping dns upcall: %s", __func__, name); | |
129 | if (is_ip(name)) { | 96 | *ip_addr = name; |
130 | cFYI(1, "%s: it is IP, skipping dns upcall: %s", | 97 | return 0; |
131 | __func__, name); | ||
132 | data = name; | ||
133 | goto skip_upcall; | ||
134 | } | ||
135 | |||
136 | rkey = request_key(&key_type_dns_resolver, name, ""); | ||
137 | if (!IS_ERR(rkey)) { | ||
138 | len = rkey->type_data.x[0]; | ||
139 | data = rkey->payload.data; | ||
140 | } else { | ||
141 | cERROR(1, "%s: unable to resolve: %s", __func__, name); | ||
142 | goto out; | ||
143 | } | ||
144 | |||
145 | skip_upcall: | ||
146 | if (data) { | ||
147 | *ip_addr = kmalloc(len + 1, GFP_KERNEL); | ||
148 | if (*ip_addr) { | ||
149 | memcpy(*ip_addr, data, len + 1); | ||
150 | if (!IS_ERR(rkey)) | ||
151 | cFYI(1, "%s: resolved: %s to %s", __func__, | ||
152 | name, | ||
153 | *ip_addr | ||
154 | ); | ||
155 | rc = 0; | ||
156 | } else { | ||
157 | rc = -ENOMEM; | ||
158 | } | ||
159 | if (!IS_ERR(rkey)) | ||
160 | key_put(rkey); | ||
161 | } | ||
162 | |||
163 | out: | ||
164 | kfree(name); | ||
165 | return rc; | ||
166 | } | 98 | } |
167 | |||
168 | |||
diff --git a/fs/cifs/dns_resolve.h b/fs/cifs/dns_resolve.h index 966e9288930b..d3f5d27f4d06 100644 --- a/fs/cifs/dns_resolve.h +++ b/fs/cifs/dns_resolve.h | |||
@@ -24,8 +24,6 @@ | |||
24 | #define _DNS_RESOLVE_H | 24 | #define _DNS_RESOLVE_H |
25 | 25 | ||
26 | #ifdef __KERNEL__ | 26 | #ifdef __KERNEL__ |
27 | #include <linux/key-type.h> | ||
28 | extern struct key_type key_type_dns_resolver; | ||
29 | extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr); | 27 | extern int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr); |
30 | #endif /* KERNEL */ | 28 | #endif /* KERNEL */ |
31 | 29 | ||
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 409e4f523e61..db11fdef0e92 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "cifs_unicode.h" | 40 | #include "cifs_unicode.h" |
41 | #include "cifs_debug.h" | 41 | #include "cifs_debug.h" |
42 | #include "cifs_fs_sb.h" | 42 | #include "cifs_fs_sb.h" |
43 | #include "fscache.h" | ||
43 | 44 | ||
44 | static inline int cifs_convert_flags(unsigned int flags) | 45 | static inline int cifs_convert_flags(unsigned int flags) |
45 | { | 46 | { |
@@ -282,6 +283,9 @@ int cifs_open(struct inode *inode, struct file *file) | |||
282 | CIFSSMBClose(xid, tcon, netfid); | 283 | CIFSSMBClose(xid, tcon, netfid); |
283 | rc = -ENOMEM; | 284 | rc = -ENOMEM; |
284 | } | 285 | } |
286 | |||
287 | cifs_fscache_set_inode_cookie(inode, file); | ||
288 | |||
285 | goto out; | 289 | goto out; |
286 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { | 290 | } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { |
287 | if (tcon->ses->serverNOS) | 291 | if (tcon->ses->serverNOS) |
@@ -373,6 +377,8 @@ int cifs_open(struct inode *inode, struct file *file) | |||
373 | goto out; | 377 | goto out; |
374 | } | 378 | } |
375 | 379 | ||
380 | cifs_fscache_set_inode_cookie(inode, file); | ||
381 | |||
376 | if (oplock & CIFS_CREATE_ACTION) { | 382 | if (oplock & CIFS_CREATE_ACTION) { |
377 | /* time to set mode which we can not set earlier due to | 383 | /* time to set mode which we can not set earlier due to |
378 | problems creating new read-only files */ | 384 | problems creating new read-only files */ |
@@ -427,7 +433,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) | |||
427 | __u16 netfid; | 433 | __u16 netfid; |
428 | 434 | ||
429 | if (file->private_data) | 435 | if (file->private_data) |
430 | pCifsFile = (struct cifsFileInfo *)file->private_data; | 436 | pCifsFile = file->private_data; |
431 | else | 437 | else |
432 | return -EBADF; | 438 | return -EBADF; |
433 | 439 | ||
@@ -565,8 +571,7 @@ int cifs_close(struct inode *inode, struct file *file) | |||
565 | int xid, timeout; | 571 | int xid, timeout; |
566 | struct cifs_sb_info *cifs_sb; | 572 | struct cifs_sb_info *cifs_sb; |
567 | struct cifsTconInfo *pTcon; | 573 | struct cifsTconInfo *pTcon; |
568 | struct cifsFileInfo *pSMBFile = | 574 | struct cifsFileInfo *pSMBFile = file->private_data; |
569 | (struct cifsFileInfo *)file->private_data; | ||
570 | 575 | ||
571 | xid = GetXid(); | 576 | xid = GetXid(); |
572 | 577 | ||
@@ -641,8 +646,7 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
641 | { | 646 | { |
642 | int rc = 0; | 647 | int rc = 0; |
643 | int xid; | 648 | int xid; |
644 | struct cifsFileInfo *pCFileStruct = | 649 | struct cifsFileInfo *pCFileStruct = file->private_data; |
645 | (struct cifsFileInfo *)file->private_data; | ||
646 | char *ptmp; | 650 | char *ptmp; |
647 | 651 | ||
648 | cFYI(1, "Closedir inode = 0x%p", inode); | 652 | cFYI(1, "Closedir inode = 0x%p", inode); |
@@ -863,8 +867,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
863 | length, pfLock, | 867 | length, pfLock, |
864 | posix_lock_type, wait_flag); | 868 | posix_lock_type, wait_flag); |
865 | } else { | 869 | } else { |
866 | struct cifsFileInfo *fid = | 870 | struct cifsFileInfo *fid = file->private_data; |
867 | (struct cifsFileInfo *)file->private_data; | ||
868 | 871 | ||
869 | if (numLock) { | 872 | if (numLock) { |
870 | rc = CIFSSMBLock(xid, tcon, netfid, length, | 873 | rc = CIFSSMBLock(xid, tcon, netfid, length, |
@@ -965,7 +968,7 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
965 | 968 | ||
966 | if (file->private_data == NULL) | 969 | if (file->private_data == NULL) |
967 | return -EBADF; | 970 | return -EBADF; |
968 | open_file = (struct cifsFileInfo *) file->private_data; | 971 | open_file = file->private_data; |
969 | 972 | ||
970 | rc = generic_write_checks(file, poffset, &write_size, 0); | 973 | rc = generic_write_checks(file, poffset, &write_size, 0); |
971 | if (rc) | 974 | if (rc) |
@@ -1067,7 +1070,7 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
1067 | 1070 | ||
1068 | if (file->private_data == NULL) | 1071 | if (file->private_data == NULL) |
1069 | return -EBADF; | 1072 | return -EBADF; |
1070 | open_file = (struct cifsFileInfo *)file->private_data; | 1073 | open_file = file->private_data; |
1071 | 1074 | ||
1072 | xid = GetXid(); | 1075 | xid = GetXid(); |
1073 | 1076 | ||
@@ -1651,8 +1654,7 @@ int cifs_fsync(struct file *file, int datasync) | |||
1651 | int xid; | 1654 | int xid; |
1652 | int rc = 0; | 1655 | int rc = 0; |
1653 | struct cifsTconInfo *tcon; | 1656 | struct cifsTconInfo *tcon; |
1654 | struct cifsFileInfo *smbfile = | 1657 | struct cifsFileInfo *smbfile = file->private_data; |
1655 | (struct cifsFileInfo *)file->private_data; | ||
1656 | struct inode *inode = file->f_path.dentry->d_inode; | 1658 | struct inode *inode = file->f_path.dentry->d_inode; |
1657 | 1659 | ||
1658 | xid = GetXid(); | 1660 | xid = GetXid(); |
@@ -1756,7 +1758,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
1756 | FreeXid(xid); | 1758 | FreeXid(xid); |
1757 | return rc; | 1759 | return rc; |
1758 | } | 1760 | } |
1759 | open_file = (struct cifsFileInfo *)file->private_data; | 1761 | open_file = file->private_data; |
1760 | 1762 | ||
1761 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1763 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
1762 | cFYI(1, "attempting read on write only file instance"); | 1764 | cFYI(1, "attempting read on write only file instance"); |
@@ -1837,7 +1839,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
1837 | FreeXid(xid); | 1839 | FreeXid(xid); |
1838 | return rc; | 1840 | return rc; |
1839 | } | 1841 | } |
1840 | open_file = (struct cifsFileInfo *)file->private_data; | 1842 | open_file = file->private_data; |
1841 | 1843 | ||
1842 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) | 1844 | if ((file->f_flags & O_ACCMODE) == O_WRONLY) |
1843 | cFYI(1, "attempting read on write only file instance"); | 1845 | cFYI(1, "attempting read on write only file instance"); |
@@ -1942,6 +1944,9 @@ static void cifs_copy_cache_pages(struct address_space *mapping, | |||
1942 | SetPageUptodate(page); | 1944 | SetPageUptodate(page); |
1943 | unlock_page(page); | 1945 | unlock_page(page); |
1944 | data += PAGE_CACHE_SIZE; | 1946 | data += PAGE_CACHE_SIZE; |
1947 | |||
1948 | /* add page to FS-Cache */ | ||
1949 | cifs_readpage_to_fscache(mapping->host, page); | ||
1945 | } | 1950 | } |
1946 | return; | 1951 | return; |
1947 | } | 1952 | } |
@@ -1968,10 +1973,19 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
1968 | FreeXid(xid); | 1973 | FreeXid(xid); |
1969 | return rc; | 1974 | return rc; |
1970 | } | 1975 | } |
1971 | open_file = (struct cifsFileInfo *)file->private_data; | 1976 | open_file = file->private_data; |
1972 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1977 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
1973 | pTcon = cifs_sb->tcon; | 1978 | pTcon = cifs_sb->tcon; |
1974 | 1979 | ||
1980 | /* | ||
1981 | * Reads as many pages as possible from fscache. Returns -ENOBUFS | ||
1982 | * immediately if the cookie is negative | ||
1983 | */ | ||
1984 | rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list, | ||
1985 | &num_pages); | ||
1986 | if (rc == 0) | ||
1987 | goto read_complete; | ||
1988 | |||
1975 | cFYI(DBG2, "rpages: num pages %d", num_pages); | 1989 | cFYI(DBG2, "rpages: num pages %d", num_pages); |
1976 | for (i = 0; i < num_pages; ) { | 1990 | for (i = 0; i < num_pages; ) { |
1977 | unsigned contig_pages; | 1991 | unsigned contig_pages; |
@@ -2082,6 +2096,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
2082 | smb_read_data = NULL; | 2096 | smb_read_data = NULL; |
2083 | } | 2097 | } |
2084 | 2098 | ||
2099 | read_complete: | ||
2085 | FreeXid(xid); | 2100 | FreeXid(xid); |
2086 | return rc; | 2101 | return rc; |
2087 | } | 2102 | } |
@@ -2092,6 +2107,11 @@ static int cifs_readpage_worker(struct file *file, struct page *page, | |||
2092 | char *read_data; | 2107 | char *read_data; |
2093 | int rc; | 2108 | int rc; |
2094 | 2109 | ||
2110 | /* Is the page cached? */ | ||
2111 | rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page); | ||
2112 | if (rc == 0) | ||
2113 | goto read_complete; | ||
2114 | |||
2095 | page_cache_get(page); | 2115 | page_cache_get(page); |
2096 | read_data = kmap(page); | 2116 | read_data = kmap(page); |
2097 | /* for reads over a certain size could initiate async read ahead */ | 2117 | /* for reads over a certain size could initiate async read ahead */ |
@@ -2111,11 +2131,17 @@ static int cifs_readpage_worker(struct file *file, struct page *page, | |||
2111 | 2131 | ||
2112 | flush_dcache_page(page); | 2132 | flush_dcache_page(page); |
2113 | SetPageUptodate(page); | 2133 | SetPageUptodate(page); |
2134 | |||
2135 | /* send this page to the cache */ | ||
2136 | cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page); | ||
2137 | |||
2114 | rc = 0; | 2138 | rc = 0; |
2115 | 2139 | ||
2116 | io_error: | 2140 | io_error: |
2117 | kunmap(page); | 2141 | kunmap(page); |
2118 | page_cache_release(page); | 2142 | page_cache_release(page); |
2143 | |||
2144 | read_complete: | ||
2119 | return rc; | 2145 | return rc; |
2120 | } | 2146 | } |
2121 | 2147 | ||
@@ -2265,8 +2291,23 @@ out: | |||
2265 | return rc; | 2291 | return rc; |
2266 | } | 2292 | } |
2267 | 2293 | ||
2268 | static void | 2294 | static int cifs_release_page(struct page *page, gfp_t gfp) |
2269 | cifs_oplock_break(struct slow_work *work) | 2295 | { |
2296 | if (PagePrivate(page)) | ||
2297 | return 0; | ||
2298 | |||
2299 | return cifs_fscache_release_page(page, gfp); | ||
2300 | } | ||
2301 | |||
2302 | static void cifs_invalidate_page(struct page *page, unsigned long offset) | ||
2303 | { | ||
2304 | struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host); | ||
2305 | |||
2306 | if (offset == 0) | ||
2307 | cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); | ||
2308 | } | ||
2309 | |||
2310 | void cifs_oplock_break(struct work_struct *work) | ||
2270 | { | 2311 | { |
2271 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | 2312 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, |
2272 | oplock_break); | 2313 | oplock_break); |
@@ -2303,33 +2344,30 @@ cifs_oplock_break(struct slow_work *work) | |||
2303 | LOCKING_ANDX_OPLOCK_RELEASE, false); | 2344 | LOCKING_ANDX_OPLOCK_RELEASE, false); |
2304 | cFYI(1, "Oplock release rc = %d", rc); | 2345 | cFYI(1, "Oplock release rc = %d", rc); |
2305 | } | 2346 | } |
2347 | |||
2348 | /* | ||
2349 | * We might have kicked in before is_valid_oplock_break() | ||
2350 | * finished grabbing reference for us. Make sure it's done by | ||
2351 | * waiting for GlobalSMSSeslock. | ||
2352 | */ | ||
2353 | write_lock(&GlobalSMBSeslock); | ||
2354 | write_unlock(&GlobalSMBSeslock); | ||
2355 | |||
2356 | cifs_oplock_break_put(cfile); | ||
2306 | } | 2357 | } |
2307 | 2358 | ||
2308 | static int | 2359 | void cifs_oplock_break_get(struct cifsFileInfo *cfile) |
2309 | cifs_oplock_break_get(struct slow_work *work) | ||
2310 | { | 2360 | { |
2311 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | ||
2312 | oplock_break); | ||
2313 | mntget(cfile->mnt); | 2361 | mntget(cfile->mnt); |
2314 | cifsFileInfo_get(cfile); | 2362 | cifsFileInfo_get(cfile); |
2315 | return 0; | ||
2316 | } | 2363 | } |
2317 | 2364 | ||
2318 | static void | 2365 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) |
2319 | cifs_oplock_break_put(struct slow_work *work) | ||
2320 | { | 2366 | { |
2321 | struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, | ||
2322 | oplock_break); | ||
2323 | mntput(cfile->mnt); | 2367 | mntput(cfile->mnt); |
2324 | cifsFileInfo_put(cfile); | 2368 | cifsFileInfo_put(cfile); |
2325 | } | 2369 | } |
2326 | 2370 | ||
2327 | const struct slow_work_ops cifs_oplock_break_ops = { | ||
2328 | .get_ref = cifs_oplock_break_get, | ||
2329 | .put_ref = cifs_oplock_break_put, | ||
2330 | .execute = cifs_oplock_break, | ||
2331 | }; | ||
2332 | |||
2333 | const struct address_space_operations cifs_addr_ops = { | 2371 | const struct address_space_operations cifs_addr_ops = { |
2334 | .readpage = cifs_readpage, | 2372 | .readpage = cifs_readpage, |
2335 | .readpages = cifs_readpages, | 2373 | .readpages = cifs_readpages, |
@@ -2338,6 +2376,8 @@ const struct address_space_operations cifs_addr_ops = { | |||
2338 | .write_begin = cifs_write_begin, | 2376 | .write_begin = cifs_write_begin, |
2339 | .write_end = cifs_write_end, | 2377 | .write_end = cifs_write_end, |
2340 | .set_page_dirty = __set_page_dirty_nobuffers, | 2378 | .set_page_dirty = __set_page_dirty_nobuffers, |
2379 | .releasepage = cifs_release_page, | ||
2380 | .invalidatepage = cifs_invalidate_page, | ||
2341 | /* .sync_page = cifs_sync_page, */ | 2381 | /* .sync_page = cifs_sync_page, */ |
2342 | /* .direct_IO = */ | 2382 | /* .direct_IO = */ |
2343 | }; | 2383 | }; |
@@ -2354,6 +2394,8 @@ const struct address_space_operations cifs_addr_ops_smallbuf = { | |||
2354 | .write_begin = cifs_write_begin, | 2394 | .write_begin = cifs_write_begin, |
2355 | .write_end = cifs_write_end, | 2395 | .write_end = cifs_write_end, |
2356 | .set_page_dirty = __set_page_dirty_nobuffers, | 2396 | .set_page_dirty = __set_page_dirty_nobuffers, |
2397 | .releasepage = cifs_release_page, | ||
2398 | .invalidatepage = cifs_invalidate_page, | ||
2357 | /* .sync_page = cifs_sync_page, */ | 2399 | /* .sync_page = cifs_sync_page, */ |
2358 | /* .direct_IO = */ | 2400 | /* .direct_IO = */ |
2359 | }; | 2401 | }; |
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c new file mode 100644 index 000000000000..9f3f5c4be161 --- /dev/null +++ b/fs/cifs/fscache.c | |||
@@ -0,0 +1,236 @@ | |||
1 | /* | ||
2 | * fs/cifs/fscache.c - CIFS filesystem cache interface | ||
3 | * | ||
4 | * Copyright (c) 2010 Novell, Inc. | ||
5 | * Author(s): Suresh Jayaraman (sjayaraman@suse.de> | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as published | ||
9 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
15 | * the GNU Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public License | ||
18 | * along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | #include "fscache.h" | ||
22 | #include "cifsglob.h" | ||
23 | #include "cifs_debug.h" | ||
24 | #include "cifs_fs_sb.h" | ||
25 | |||
26 | void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) | ||
27 | { | ||
28 | server->fscache = | ||
29 | fscache_acquire_cookie(cifs_fscache_netfs.primary_index, | ||
30 | &cifs_fscache_server_index_def, server); | ||
31 | cFYI(1, "CIFS: get client cookie (0x%p/0x%p)", server, | ||
32 | server->fscache); | ||
33 | } | ||
34 | |||
35 | void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) | ||
36 | { | ||
37 | cFYI(1, "CIFS: release client cookie (0x%p/0x%p)", server, | ||
38 | server->fscache); | ||
39 | fscache_relinquish_cookie(server->fscache, 0); | ||
40 | server->fscache = NULL; | ||
41 | } | ||
42 | |||
43 | void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon) | ||
44 | { | ||
45 | struct TCP_Server_Info *server = tcon->ses->server; | ||
46 | |||
47 | tcon->fscache = | ||
48 | fscache_acquire_cookie(server->fscache, | ||
49 | &cifs_fscache_super_index_def, tcon); | ||
50 | cFYI(1, "CIFS: get superblock cookie (0x%p/0x%p)", | ||
51 | server->fscache, tcon->fscache); | ||
52 | } | ||
53 | |||
54 | void cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) | ||
55 | { | ||
56 | cFYI(1, "CIFS: releasing superblock cookie (0x%p)", tcon->fscache); | ||
57 | fscache_relinquish_cookie(tcon->fscache, 0); | ||
58 | tcon->fscache = NULL; | ||
59 | } | ||
60 | |||
61 | static void cifs_fscache_enable_inode_cookie(struct inode *inode) | ||
62 | { | ||
63 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | ||
64 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
65 | |||
66 | if (cifsi->fscache) | ||
67 | return; | ||
68 | |||
69 | cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache, | ||
70 | &cifs_fscache_inode_object_def, | ||
71 | cifsi); | ||
72 | cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", | ||
73 | cifs_sb->tcon->fscache, cifsi->fscache); | ||
74 | } | ||
75 | |||
76 | void cifs_fscache_release_inode_cookie(struct inode *inode) | ||
77 | { | ||
78 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | ||
79 | |||
80 | if (cifsi->fscache) { | ||
81 | cFYI(1, "CIFS releasing inode cookie (0x%p)", | ||
82 | cifsi->fscache); | ||
83 | fscache_relinquish_cookie(cifsi->fscache, 0); | ||
84 | cifsi->fscache = NULL; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static void cifs_fscache_disable_inode_cookie(struct inode *inode) | ||
89 | { | ||
90 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | ||
91 | |||
92 | if (cifsi->fscache) { | ||
93 | cFYI(1, "CIFS disabling inode cookie (0x%p)", | ||
94 | cifsi->fscache); | ||
95 | fscache_relinquish_cookie(cifsi->fscache, 1); | ||
96 | cifsi->fscache = NULL; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp) | ||
101 | { | ||
102 | if ((filp->f_flags & O_ACCMODE) != O_RDONLY) | ||
103 | cifs_fscache_disable_inode_cookie(inode); | ||
104 | else { | ||
105 | cifs_fscache_enable_inode_cookie(inode); | ||
106 | cFYI(1, "CIFS: fscache inode cookie set"); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | void cifs_fscache_reset_inode_cookie(struct inode *inode) | ||
111 | { | ||
112 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | ||
113 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
114 | struct fscache_cookie *old = cifsi->fscache; | ||
115 | |||
116 | if (cifsi->fscache) { | ||
117 | /* retire the current fscache cache and get a new one */ | ||
118 | fscache_relinquish_cookie(cifsi->fscache, 1); | ||
119 | |||
120 | cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache, | ||
121 | &cifs_fscache_inode_object_def, | ||
122 | cifsi); | ||
123 | cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p", | ||
124 | cifsi->fscache, old); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | int cifs_fscache_release_page(struct page *page, gfp_t gfp) | ||
129 | { | ||
130 | if (PageFsCache(page)) { | ||
131 | struct inode *inode = page->mapping->host; | ||
132 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | ||
133 | |||
134 | cFYI(1, "CIFS: fscache release page (0x%p/0x%p)", | ||
135 | page, cifsi->fscache); | ||
136 | if (!fscache_maybe_release_page(cifsi->fscache, page, gfp)) | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | return 1; | ||
141 | } | ||
142 | |||
143 | static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx, | ||
144 | int error) | ||
145 | { | ||
146 | cFYI(1, "CFS: readpage_from_fscache_complete (0x%p/%d)", | ||
147 | page, error); | ||
148 | if (!error) | ||
149 | SetPageUptodate(page); | ||
150 | unlock_page(page); | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * Retrieve a page from FS-Cache | ||
155 | */ | ||
156 | int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) | ||
157 | { | ||
158 | int ret; | ||
159 | |||
160 | cFYI(1, "CIFS: readpage_from_fscache(fsc:%p, p:%p, i:0x%p", | ||
161 | CIFS_I(inode)->fscache, page, inode); | ||
162 | ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page, | ||
163 | cifs_readpage_from_fscache_complete, | ||
164 | NULL, | ||
165 | GFP_KERNEL); | ||
166 | switch (ret) { | ||
167 | |||
168 | case 0: /* page found in fscache, read submitted */ | ||
169 | cFYI(1, "CIFS: readpage_from_fscache: submitted"); | ||
170 | return ret; | ||
171 | case -ENOBUFS: /* page won't be cached */ | ||
172 | case -ENODATA: /* page not in cache */ | ||
173 | cFYI(1, "CIFS: readpage_from_fscache %d", ret); | ||
174 | return 1; | ||
175 | |||
176 | default: | ||
177 | cERROR(1, "unknown error ret = %d", ret); | ||
178 | } | ||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | /* | ||
183 | * Retrieve a set of pages from FS-Cache | ||
184 | */ | ||
185 | int __cifs_readpages_from_fscache(struct inode *inode, | ||
186 | struct address_space *mapping, | ||
187 | struct list_head *pages, | ||
188 | unsigned *nr_pages) | ||
189 | { | ||
190 | int ret; | ||
191 | |||
192 | cFYI(1, "CIFS: __cifs_readpages_from_fscache (0x%p/%u/0x%p)", | ||
193 | CIFS_I(inode)->fscache, *nr_pages, inode); | ||
194 | ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping, | ||
195 | pages, nr_pages, | ||
196 | cifs_readpage_from_fscache_complete, | ||
197 | NULL, | ||
198 | mapping_gfp_mask(mapping)); | ||
199 | switch (ret) { | ||
200 | case 0: /* read submitted to the cache for all pages */ | ||
201 | cFYI(1, "CIFS: readpages_from_fscache: submitted"); | ||
202 | return ret; | ||
203 | |||
204 | case -ENOBUFS: /* some pages are not cached and can't be */ | ||
205 | case -ENODATA: /* some pages are not cached */ | ||
206 | cFYI(1, "CIFS: readpages_from_fscache: no page"); | ||
207 | return 1; | ||
208 | |||
209 | default: | ||
210 | cFYI(1, "unknown error ret = %d", ret); | ||
211 | } | ||
212 | |||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) | ||
217 | { | ||
218 | int ret; | ||
219 | |||
220 | cFYI(1, "CIFS: readpage_to_fscache(fsc: %p, p: %p, i: %p", | ||
221 | CIFS_I(inode)->fscache, page, inode); | ||
222 | ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL); | ||
223 | if (ret != 0) | ||
224 | fscache_uncache_page(CIFS_I(inode)->fscache, page); | ||
225 | } | ||
226 | |||
227 | void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode) | ||
228 | { | ||
229 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | ||
230 | struct fscache_cookie *cookie = cifsi->fscache; | ||
231 | |||
232 | cFYI(1, "CIFS: fscache invalidatepage (0x%p/0x%p)", page, cookie); | ||
233 | fscache_wait_on_page_write(cookie, page); | ||
234 | fscache_uncache_page(cookie, page); | ||
235 | } | ||
236 | |||
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h new file mode 100644 index 000000000000..31b88ec2341e --- /dev/null +++ b/fs/cifs/fscache.h | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * fs/cifs/fscache.h - CIFS filesystem cache interface definitions | ||
3 | * | ||
4 | * Copyright (c) 2010 Novell, Inc. | ||
5 | * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU Lesser General Public License as published | ||
9 | * by the Free Software Foundation; either version 2.1 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
15 | * the GNU Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public License | ||
18 | * along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | #ifndef _CIFS_FSCACHE_H | ||
22 | #define _CIFS_FSCACHE_H | ||
23 | |||
24 | #include <linux/fscache.h> | ||
25 | |||
26 | #include "cifsglob.h" | ||
27 | |||
28 | #ifdef CONFIG_CIFS_FSCACHE | ||
29 | |||
30 | extern struct fscache_netfs cifs_fscache_netfs; | ||
31 | extern const struct fscache_cookie_def cifs_fscache_server_index_def; | ||
32 | extern const struct fscache_cookie_def cifs_fscache_super_index_def; | ||
33 | extern const struct fscache_cookie_def cifs_fscache_inode_object_def; | ||
34 | |||
35 | extern int cifs_fscache_register(void); | ||
36 | extern void cifs_fscache_unregister(void); | ||
37 | |||
38 | /* | ||
39 | * fscache.c | ||
40 | */ | ||
41 | extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *); | ||
42 | extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *); | ||
43 | extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *); | ||
44 | extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *); | ||
45 | |||
46 | extern void cifs_fscache_release_inode_cookie(struct inode *); | ||
47 | extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *); | ||
48 | extern void cifs_fscache_reset_inode_cookie(struct inode *); | ||
49 | |||
50 | extern void __cifs_fscache_invalidate_page(struct page *, struct inode *); | ||
51 | extern int cifs_fscache_release_page(struct page *page, gfp_t gfp); | ||
52 | extern int __cifs_readpage_from_fscache(struct inode *, struct page *); | ||
53 | extern int __cifs_readpages_from_fscache(struct inode *, | ||
54 | struct address_space *, | ||
55 | struct list_head *, | ||
56 | unsigned *); | ||
57 | |||
58 | extern void __cifs_readpage_to_fscache(struct inode *, struct page *); | ||
59 | |||
60 | static inline void cifs_fscache_invalidate_page(struct page *page, | ||
61 | struct inode *inode) | ||
62 | { | ||
63 | if (PageFsCache(page)) | ||
64 | __cifs_fscache_invalidate_page(page, inode); | ||
65 | } | ||
66 | |||
67 | static inline int cifs_readpage_from_fscache(struct inode *inode, | ||
68 | struct page *page) | ||
69 | { | ||
70 | if (CIFS_I(inode)->fscache) | ||
71 | return __cifs_readpage_from_fscache(inode, page); | ||
72 | |||
73 | return -ENOBUFS; | ||
74 | } | ||
75 | |||
76 | static inline int cifs_readpages_from_fscache(struct inode *inode, | ||
77 | struct address_space *mapping, | ||
78 | struct list_head *pages, | ||
79 | unsigned *nr_pages) | ||
80 | { | ||
81 | if (CIFS_I(inode)->fscache) | ||
82 | return __cifs_readpages_from_fscache(inode, mapping, pages, | ||
83 | nr_pages); | ||
84 | return -ENOBUFS; | ||
85 | } | ||
86 | |||
87 | static inline void cifs_readpage_to_fscache(struct inode *inode, | ||
88 | struct page *page) | ||
89 | { | ||
90 | if (PageFsCache(page)) | ||
91 | __cifs_readpage_to_fscache(inode, page); | ||
92 | } | ||
93 | |||
94 | #else /* CONFIG_CIFS_FSCACHE */ | ||
95 | static inline int cifs_fscache_register(void) { return 0; } | ||
96 | static inline void cifs_fscache_unregister(void) {} | ||
97 | |||
98 | static inline void | ||
99 | cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {} | ||
100 | static inline void | ||
101 | cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) {} | ||
102 | static inline void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon) {} | ||
103 | static inline void | ||
104 | cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {} | ||
105 | |||
106 | static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {} | ||
107 | static inline void cifs_fscache_set_inode_cookie(struct inode *inode, | ||
108 | struct file *filp) {} | ||
109 | static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {} | ||
110 | static inline int cifs_fscache_release_page(struct page *page, gfp_t gfp) | ||
111 | { | ||
112 | return 1; /* May release page */ | ||
113 | } | ||
114 | |||
115 | static inline void cifs_fscache_invalidate_page(struct page *page, | ||
116 | struct inode *inode) {} | ||
117 | static inline int | ||
118 | cifs_readpage_from_fscache(struct inode *inode, struct page *page) | ||
119 | { | ||
120 | return -ENOBUFS; | ||
121 | } | ||
122 | |||
123 | static inline int cifs_readpages_from_fscache(struct inode *inode, | ||
124 | struct address_space *mapping, | ||
125 | struct list_head *pages, | ||
126 | unsigned *nr_pages) | ||
127 | { | ||
128 | return -ENOBUFS; | ||
129 | } | ||
130 | |||
131 | static inline void cifs_readpage_to_fscache(struct inode *inode, | ||
132 | struct page *page) {} | ||
133 | |||
134 | #endif /* CONFIG_CIFS_FSCACHE */ | ||
135 | |||
136 | #endif /* _CIFS_FSCACHE_H */ | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 6f0683c68952..dc4c47ab9588 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "cifsproto.h" | 29 | #include "cifsproto.h" |
30 | #include "cifs_debug.h" | 30 | #include "cifs_debug.h" |
31 | #include "cifs_fs_sb.h" | 31 | #include "cifs_fs_sb.h" |
32 | #include "fscache.h" | ||
32 | 33 | ||
33 | 34 | ||
34 | static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) | 35 | static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral) |
@@ -288,7 +289,7 @@ int cifs_get_file_info_unix(struct file *filp) | |||
288 | struct inode *inode = filp->f_path.dentry->d_inode; | 289 | struct inode *inode = filp->f_path.dentry->d_inode; |
289 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 290 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
290 | struct cifsTconInfo *tcon = cifs_sb->tcon; | 291 | struct cifsTconInfo *tcon = cifs_sb->tcon; |
291 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | 292 | struct cifsFileInfo *cfile = filp->private_data; |
292 | 293 | ||
293 | xid = GetXid(); | 294 | xid = GetXid(); |
294 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); | 295 | rc = CIFSSMBUnixQFileInfo(xid, tcon, cfile->netfid, &find_data); |
@@ -515,7 +516,7 @@ int cifs_get_file_info(struct file *filp) | |||
515 | struct inode *inode = filp->f_path.dentry->d_inode; | 516 | struct inode *inode = filp->f_path.dentry->d_inode; |
516 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 517 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
517 | struct cifsTconInfo *tcon = cifs_sb->tcon; | 518 | struct cifsTconInfo *tcon = cifs_sb->tcon; |
518 | struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data; | 519 | struct cifsFileInfo *cfile = filp->private_data; |
519 | 520 | ||
520 | xid = GetXid(); | 521 | xid = GetXid(); |
521 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); | 522 | rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data); |
@@ -723,18 +724,17 @@ cifs_find_inode(struct inode *inode, void *opaque) | |||
723 | { | 724 | { |
724 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; | 725 | struct cifs_fattr *fattr = (struct cifs_fattr *) opaque; |
725 | 726 | ||
727 | /* don't match inode with different uniqueid */ | ||
726 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) | 728 | if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid) |
727 | return 0; | 729 | return 0; |
728 | 730 | ||
729 | /* | 731 | /* don't match inode of different type */ |
730 | * uh oh -- it's a directory. We can't use it since hardlinked dirs are | 732 | if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT)) |
731 | * verboten. Disable serverino and return it as if it were found, the | 733 | return 0; |
732 | * caller can discard it, generate a uniqueid and retry the find | 734 | |
733 | */ | 735 | /* if it's not a directory or has no dentries, then flag it */ |
734 | if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) { | 736 | if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry)) |
735 | fattr->cf_flags |= CIFS_FATTR_INO_COLLISION; | 737 | fattr->cf_flags |= CIFS_FATTR_INO_COLLISION; |
736 | cifs_autodisable_serverino(CIFS_SB(inode->i_sb)); | ||
737 | } | ||
738 | 738 | ||
739 | return 1; | 739 | return 1; |
740 | } | 740 | } |
@@ -748,6 +748,27 @@ cifs_init_inode(struct inode *inode, void *opaque) | |||
748 | return 0; | 748 | return 0; |
749 | } | 749 | } |
750 | 750 | ||
751 | /* | ||
752 | * walk dentry list for an inode and report whether it has aliases that | ||
753 | * are hashed. We use this to determine if a directory inode can actually | ||
754 | * be used. | ||
755 | */ | ||
756 | static bool | ||
757 | inode_has_hashed_dentries(struct inode *inode) | ||
758 | { | ||
759 | struct dentry *dentry; | ||
760 | |||
761 | spin_lock(&dcache_lock); | ||
762 | list_for_each_entry(dentry, &inode->i_dentry, d_alias) { | ||
763 | if (!d_unhashed(dentry) || IS_ROOT(dentry)) { | ||
764 | spin_unlock(&dcache_lock); | ||
765 | return true; | ||
766 | } | ||
767 | } | ||
768 | spin_unlock(&dcache_lock); | ||
769 | return false; | ||
770 | } | ||
771 | |||
751 | /* Given fattrs, get a corresponding inode */ | 772 | /* Given fattrs, get a corresponding inode */ |
752 | struct inode * | 773 | struct inode * |
753 | cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) | 774 | cifs_iget(struct super_block *sb, struct cifs_fattr *fattr) |
@@ -763,12 +784,16 @@ retry_iget5_locked: | |||
763 | 784 | ||
764 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); | 785 | inode = iget5_locked(sb, hash, cifs_find_inode, cifs_init_inode, fattr); |
765 | if (inode) { | 786 | if (inode) { |
766 | /* was there a problematic inode number collision? */ | 787 | /* was there a potentially problematic inode collision? */ |
767 | if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) { | 788 | if (fattr->cf_flags & CIFS_FATTR_INO_COLLISION) { |
768 | iput(inode); | ||
769 | fattr->cf_uniqueid = iunique(sb, ROOT_I); | ||
770 | fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION; | 789 | fattr->cf_flags &= ~CIFS_FATTR_INO_COLLISION; |
771 | goto retry_iget5_locked; | 790 | |
791 | if (inode_has_hashed_dentries(inode)) { | ||
792 | cifs_autodisable_serverino(CIFS_SB(sb)); | ||
793 | iput(inode); | ||
794 | fattr->cf_uniqueid = iunique(sb, ROOT_I); | ||
795 | goto retry_iget5_locked; | ||
796 | } | ||
772 | } | 797 | } |
773 | 798 | ||
774 | cifs_fattr_to_inode(inode, fattr); | 799 | cifs_fattr_to_inode(inode, fattr); |
@@ -776,6 +801,10 @@ retry_iget5_locked: | |||
776 | inode->i_flags |= S_NOATIME | S_NOCMTIME; | 801 | inode->i_flags |= S_NOATIME | S_NOCMTIME; |
777 | if (inode->i_state & I_NEW) { | 802 | if (inode->i_state & I_NEW) { |
778 | inode->i_ino = hash; | 803 | inode->i_ino = hash; |
804 | #ifdef CONFIG_CIFS_FSCACHE | ||
805 | /* initialize per-inode cache cookie pointer */ | ||
806 | CIFS_I(inode)->fscache = NULL; | ||
807 | #endif | ||
779 | unlock_new_inode(inode); | 808 | unlock_new_inode(inode); |
780 | } | 809 | } |
781 | } | 810 | } |
@@ -807,6 +836,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
807 | if (!inode) | 836 | if (!inode) |
808 | return ERR_PTR(-ENOMEM); | 837 | return ERR_PTR(-ENOMEM); |
809 | 838 | ||
839 | #ifdef CONFIG_CIFS_FSCACHE | ||
840 | /* populate tcon->resource_id */ | ||
841 | cifs_sb->tcon->resource_id = CIFS_I(inode)->uniqueid; | ||
842 | #endif | ||
843 | |||
810 | if (rc && cifs_sb->tcon->ipc) { | 844 | if (rc && cifs_sb->tcon->ipc) { |
811 | cFYI(1, "ipc connection - fake read inode"); | 845 | cFYI(1, "ipc connection - fake read inode"); |
812 | inode->i_mode |= S_IFDIR; | 846 | inode->i_mode |= S_IFDIR; |
@@ -1568,6 +1602,7 @@ cifs_invalidate_mapping(struct inode *inode) | |||
1568 | cifs_i->write_behind_rc = rc; | 1602 | cifs_i->write_behind_rc = rc; |
1569 | } | 1603 | } |
1570 | invalidate_remote_inode(inode); | 1604 | invalidate_remote_inode(inode); |
1605 | cifs_fscache_reset_inode_cookie(inode); | ||
1571 | } | 1606 | } |
1572 | 1607 | ||
1573 | int cifs_revalidate_file(struct file *filp) | 1608 | int cifs_revalidate_file(struct file *filp) |
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index 505926f1ee6b..9d38a71c8e14 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c | |||
@@ -41,8 +41,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) | |||
41 | __u64 ExtAttrMask = 0; | 41 | __u64 ExtAttrMask = 0; |
42 | __u64 caps; | 42 | __u64 caps; |
43 | struct cifsTconInfo *tcon; | 43 | struct cifsTconInfo *tcon; |
44 | struct cifsFileInfo *pSMBFile = | 44 | struct cifsFileInfo *pSMBFile = filep->private_data; |
45 | (struct cifsFileInfo *)filep->private_data; | ||
46 | #endif /* CONFIG_CIFS_POSIX */ | 45 | #endif /* CONFIG_CIFS_POSIX */ |
47 | 46 | ||
48 | xid = GetXid(); | 47 | xid = GetXid(); |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 1394aa37f26c..3ccadc1326d6 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -498,7 +498,6 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
498 | struct cifsTconInfo *tcon; | 498 | struct cifsTconInfo *tcon; |
499 | struct cifsInodeInfo *pCifsInode; | 499 | struct cifsInodeInfo *pCifsInode; |
500 | struct cifsFileInfo *netfile; | 500 | struct cifsFileInfo *netfile; |
501 | int rc; | ||
502 | 501 | ||
503 | cFYI(1, "Checking for oplock break or dnotify response"); | 502 | cFYI(1, "Checking for oplock break or dnotify response"); |
504 | if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && | 503 | if ((pSMB->hdr.Command == SMB_COM_NT_TRANSACT) && |
@@ -583,13 +582,18 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) | |||
583 | pCifsInode->clientCanCacheAll = false; | 582 | pCifsInode->clientCanCacheAll = false; |
584 | if (pSMB->OplockLevel == 0) | 583 | if (pSMB->OplockLevel == 0) |
585 | pCifsInode->clientCanCacheRead = false; | 584 | pCifsInode->clientCanCacheRead = false; |
586 | rc = slow_work_enqueue(&netfile->oplock_break); | 585 | |
587 | if (rc) { | 586 | /* |
588 | cERROR(1, "failed to enqueue oplock " | 587 | * cifs_oplock_break_put() can't be called |
589 | "break: %d\n", rc); | 588 | * from here. Get reference after queueing |
590 | } else { | 589 | * succeeded. cifs_oplock_break() will |
591 | netfile->oplock_break_cancelled = false; | 590 | * synchronize using GlobalSMSSeslock. |
592 | } | 591 | */ |
592 | if (queue_work(system_nrt_wq, | ||
593 | &netfile->oplock_break)) | ||
594 | cifs_oplock_break_get(netfile); | ||
595 | netfile->oplock_break_cancelled = false; | ||
596 | |||
593 | read_unlock(&GlobalSMBSeslock); | 597 | read_unlock(&GlobalSMBSeslock); |
594 | read_unlock(&cifs_tcp_ses_lock); | 598 | read_unlock(&cifs_tcp_ses_lock); |
595 | return true; | 599 | return true; |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index d35d52889cb5..f97851119e6c 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
@@ -61,6 +61,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = { | |||
61 | {ERRremcd, -EACCES}, | 61 | {ERRremcd, -EACCES}, |
62 | {ERRdiffdevice, -EXDEV}, | 62 | {ERRdiffdevice, -EXDEV}, |
63 | {ERRnofiles, -ENOENT}, | 63 | {ERRnofiles, -ENOENT}, |
64 | {ERRwriteprot, -EROFS}, | ||
64 | {ERRbadshare, -ETXTBSY}, | 65 | {ERRbadshare, -ETXTBSY}, |
65 | {ERRlock, -EACCES}, | 66 | {ERRlock, -EACCES}, |
66 | {ERRunsup, -EINVAL}, | 67 | {ERRunsup, -EINVAL}, |
@@ -139,17 +140,18 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { | |||
139 | * Returns 0 on failure. | 140 | * Returns 0 on failure. |
140 | */ | 141 | */ |
141 | static int | 142 | static int |
142 | cifs_inet_pton(const int address_family, const char *cp, void *dst) | 143 | cifs_inet_pton(const int address_family, const char *cp, int len, void *dst) |
143 | { | 144 | { |
144 | int ret = 0; | 145 | int ret = 0; |
145 | 146 | ||
146 | /* calculate length by finding first slash or NULL */ | 147 | /* calculate length by finding first slash or NULL */ |
147 | if (address_family == AF_INET) | 148 | if (address_family == AF_INET) |
148 | ret = in4_pton(cp, -1 /* len */, dst, '\\', NULL); | 149 | ret = in4_pton(cp, len, dst, '\\', NULL); |
149 | else if (address_family == AF_INET6) | 150 | else if (address_family == AF_INET6) |
150 | ret = in6_pton(cp, -1 /* len */, dst , '\\', NULL); | 151 | ret = in6_pton(cp, len, dst , '\\', NULL); |
151 | 152 | ||
152 | cFYI(DBG2, "address conversion returned %d for %s", ret, cp); | 153 | cFYI(DBG2, "address conversion returned %d for %*.*s", |
154 | ret, len, len, cp); | ||
153 | if (ret > 0) | 155 | if (ret > 0) |
154 | ret = 1; | 156 | ret = 1; |
155 | return ret; | 157 | return ret; |
@@ -164,43 +166,66 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst) | |||
164 | * Returns 0 on failure. | 166 | * Returns 0 on failure. |
165 | */ | 167 | */ |
166 | int | 168 | int |
167 | cifs_convert_address(char *src, void *dst) | 169 | cifs_convert_address(struct sockaddr *dst, const char *src, int len) |
168 | { | 170 | { |
169 | int rc; | 171 | int rc, alen, slen; |
170 | char *pct, *endp; | 172 | const char *pct; |
173 | char *endp, scope_id[13]; | ||
171 | struct sockaddr_in *s4 = (struct sockaddr_in *) dst; | 174 | struct sockaddr_in *s4 = (struct sockaddr_in *) dst; |
172 | struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; | 175 | struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; |
173 | 176 | ||
174 | /* IPv4 address */ | 177 | /* IPv4 address */ |
175 | if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) { | 178 | if (cifs_inet_pton(AF_INET, src, len, &s4->sin_addr.s_addr)) { |
176 | s4->sin_family = AF_INET; | 179 | s4->sin_family = AF_INET; |
177 | return 1; | 180 | return 1; |
178 | } | 181 | } |
179 | 182 | ||
180 | /* temporarily terminate string */ | 183 | /* attempt to exclude the scope ID from the address part */ |
181 | pct = strchr(src, '%'); | 184 | pct = memchr(src, '%', len); |
182 | if (pct) | 185 | alen = pct ? pct - src : len; |
183 | *pct = '\0'; | ||
184 | |||
185 | rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr); | ||
186 | |||
187 | /* repair temp termination (if any) and make pct point to scopeid */ | ||
188 | if (pct) | ||
189 | *pct++ = '%'; | ||
190 | 186 | ||
187 | rc = cifs_inet_pton(AF_INET6, src, alen, &s6->sin6_addr.s6_addr); | ||
191 | if (!rc) | 188 | if (!rc) |
192 | return rc; | 189 | return rc; |
193 | 190 | ||
194 | s6->sin6_family = AF_INET6; | 191 | s6->sin6_family = AF_INET6; |
195 | if (pct) { | 192 | if (pct) { |
193 | /* grab the scope ID */ | ||
194 | slen = len - (alen + 1); | ||
195 | if (slen <= 0 || slen > 12) | ||
196 | return 0; | ||
197 | memcpy(scope_id, pct + 1, slen); | ||
198 | scope_id[slen] = '\0'; | ||
199 | |||
196 | s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0); | 200 | s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0); |
197 | if (!*pct || *endp) | 201 | if (endp != scope_id + slen) |
198 | return 0; | 202 | return 0; |
199 | } | 203 | } |
200 | 204 | ||
201 | return rc; | 205 | return rc; |
202 | } | 206 | } |
203 | 207 | ||
208 | int | ||
209 | cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, | ||
210 | const unsigned short int port) | ||
211 | { | ||
212 | if (!cifs_convert_address(dst, src, len)) | ||
213 | return 0; | ||
214 | |||
215 | switch (dst->sa_family) { | ||
216 | case AF_INET: | ||
217 | ((struct sockaddr_in *)dst)->sin_port = htons(port); | ||
218 | break; | ||
219 | case AF_INET6: | ||
220 | ((struct sockaddr_in6 *)dst)->sin6_port = htons(port); | ||
221 | break; | ||
222 | default: | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | return 1; | ||
227 | } | ||
228 | |||
204 | /***************************************************************************** | 229 | /***************************************************************************** |
205 | convert a NT status code to a dos class/code | 230 | convert a NT status code to a dos class/code |
206 | *****************************************************************************/ | 231 | *****************************************************************************/ |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index daf1753af674..d5e591fab475 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
@@ -847,6 +847,11 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) | |||
847 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; | 847 | end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len; |
848 | 848 | ||
849 | tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); | 849 | tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL); |
850 | if (tmp_buf == NULL) { | ||
851 | rc = -ENOMEM; | ||
852 | break; | ||
853 | } | ||
854 | |||
850 | for (i = 0; (i < num_to_fill) && (rc == 0); i++) { | 855 | for (i = 0; (i < num_to_fill) && (rc == 0); i++) { |
851 | if (current_entry == NULL) { | 856 | if (current_entry == NULL) { |
852 | /* evaluate whether this case is an error */ | 857 | /* evaluate whether this case is an error */ |
diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h index c5084d27db7c..7f16cb825fe5 100644 --- a/fs/cifs/smberr.h +++ b/fs/cifs/smberr.h | |||
@@ -76,6 +76,7 @@ | |||
76 | #define ERRnofiles 18 /* A File Search command can find no | 76 | #define ERRnofiles 18 /* A File Search command can find no |
77 | more files matching the specified | 77 | more files matching the specified |
78 | criteria. */ | 78 | criteria. */ |
79 | #define ERRwriteprot 19 /* media is write protected */ | ||
79 | #define ERRgeneral 31 | 80 | #define ERRgeneral 31 |
80 | #define ERRbadshare 32 /* The sharing mode specified for an | 81 | #define ERRbadshare 32 /* The sharing mode specified for an |
81 | Open conflicts with existing FIDs on | 82 | Open conflicts with existing FIDs on |
diff --git a/fs/compat.c b/fs/compat.c index 6490d2134ff3..c6fda9aeb864 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) | 8 | * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) |
9 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) | 9 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) |
10 | * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs | 10 | * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs |
11 | * Copyright (C) 2003 Pavel Machek (pavel@suse.cz) | 11 | * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz) |
12 | * | 12 | * |
13 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License version 2 as | 14 | * it under the terms of the GNU General Public License version 2 as |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 618f38136304..5d9b936c458b 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) | 4 | * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) |
5 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) | 5 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) |
6 | * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs | 6 | * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs |
7 | * Copyright (C) 2003 Pavel Machek (pavel@suse.cz) | 7 | * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz) |
8 | * | 8 | * |
9 | * These routines maintain argument size conversion between 32bit and 64bit | 9 | * These routines maintain argument size conversion between 32bit and 64bit |
10 | * ioctls. | 10 | * ioctls. |
@@ -578,8 +578,11 @@ static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, | |||
578 | } | 578 | } |
579 | 579 | ||
580 | /* Bluetooth ioctls */ | 580 | /* Bluetooth ioctls */ |
581 | #define HCIUARTSETPROTO _IOW('U', 200, int) | 581 | #define HCIUARTSETPROTO _IOW('U', 200, int) |
582 | #define HCIUARTGETPROTO _IOR('U', 201, int) | 582 | #define HCIUARTGETPROTO _IOR('U', 201, int) |
583 | #define HCIUARTGETDEVICE _IOR('U', 202, int) | ||
584 | #define HCIUARTSETFLAGS _IOW('U', 203, int) | ||
585 | #define HCIUARTGETFLAGS _IOR('U', 204, int) | ||
583 | 586 | ||
584 | #define BNEPCONNADD _IOW('B', 200, int) | 587 | #define BNEPCONNADD _IOW('B', 200, int) |
585 | #define BNEPCONNDEL _IOW('B', 201, int) | 588 | #define BNEPCONNDEL _IOW('B', 201, int) |
@@ -1298,6 +1301,8 @@ COMPATIBLE_IOCTL(HCISETLINKPOL) | |||
1298 | COMPATIBLE_IOCTL(HCISETLINKMODE) | 1301 | COMPATIBLE_IOCTL(HCISETLINKMODE) |
1299 | COMPATIBLE_IOCTL(HCISETACLMTU) | 1302 | COMPATIBLE_IOCTL(HCISETACLMTU) |
1300 | COMPATIBLE_IOCTL(HCISETSCOMTU) | 1303 | COMPATIBLE_IOCTL(HCISETSCOMTU) |
1304 | COMPATIBLE_IOCTL(HCIBLOCKADDR) | ||
1305 | COMPATIBLE_IOCTL(HCIUNBLOCKADDR) | ||
1301 | COMPATIBLE_IOCTL(HCIINQUIRY) | 1306 | COMPATIBLE_IOCTL(HCIINQUIRY) |
1302 | COMPATIBLE_IOCTL(HCIUARTSETPROTO) | 1307 | COMPATIBLE_IOCTL(HCIUARTSETPROTO) |
1303 | COMPATIBLE_IOCTL(HCIUARTGETPROTO) | 1308 | COMPATIBLE_IOCTL(HCIUARTGETPROTO) |
diff --git a/fs/dcache.c b/fs/dcache.c index c8c78ba07827..86d4db15473e 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -896,7 +896,7 @@ EXPORT_SYMBOL(shrink_dcache_parent); | |||
896 | * | 896 | * |
897 | * In this case we return -1 to tell the caller that we baled. | 897 | * In this case we return -1 to tell the caller that we baled. |
898 | */ | 898 | */ |
899 | static int shrink_dcache_memory(int nr, gfp_t gfp_mask) | 899 | static int shrink_dcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
900 | { | 900 | { |
901 | if (nr) { | 901 | if (nr) { |
902 | if (!(gfp_mask & __GFP_FS)) | 902 | if (!(gfp_mask & __GFP_FS)) |
diff --git a/fs/direct-io.c b/fs/direct-io.c index 7600aacf531d..a10cb91cadea 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -218,7 +218,7 @@ static struct page *dio_get_page(struct dio *dio) | |||
218 | * filesystems can use it to hold additional state between get_block calls and | 218 | * filesystems can use it to hold additional state between get_block calls and |
219 | * dio_complete. | 219 | * dio_complete. |
220 | */ | 220 | */ |
221 | static int dio_complete(struct dio *dio, loff_t offset, int ret) | 221 | static int dio_complete(struct dio *dio, loff_t offset, int ret, bool is_async) |
222 | { | 222 | { |
223 | ssize_t transferred = 0; | 223 | ssize_t transferred = 0; |
224 | 224 | ||
@@ -239,14 +239,6 @@ static int dio_complete(struct dio *dio, loff_t offset, int ret) | |||
239 | transferred = dio->i_size - offset; | 239 | transferred = dio->i_size - offset; |
240 | } | 240 | } |
241 | 241 | ||
242 | if (dio->end_io && dio->result) | ||
243 | dio->end_io(dio->iocb, offset, transferred, | ||
244 | dio->map_bh.b_private); | ||
245 | |||
246 | if (dio->flags & DIO_LOCKING) | ||
247 | /* lockdep: non-owner release */ | ||
248 | up_read_non_owner(&dio->inode->i_alloc_sem); | ||
249 | |||
250 | if (ret == 0) | 242 | if (ret == 0) |
251 | ret = dio->page_errors; | 243 | ret = dio->page_errors; |
252 | if (ret == 0) | 244 | if (ret == 0) |
@@ -254,6 +246,17 @@ static int dio_complete(struct dio *dio, loff_t offset, int ret) | |||
254 | if (ret == 0) | 246 | if (ret == 0) |
255 | ret = transferred; | 247 | ret = transferred; |
256 | 248 | ||
249 | if (dio->end_io && dio->result) { | ||
250 | dio->end_io(dio->iocb, offset, transferred, | ||
251 | dio->map_bh.b_private, ret, is_async); | ||
252 | } else if (is_async) { | ||
253 | aio_complete(dio->iocb, ret, 0); | ||
254 | } | ||
255 | |||
256 | if (dio->flags & DIO_LOCKING) | ||
257 | /* lockdep: non-owner release */ | ||
258 | up_read_non_owner(&dio->inode->i_alloc_sem); | ||
259 | |||
257 | return ret; | 260 | return ret; |
258 | } | 261 | } |
259 | 262 | ||
@@ -277,8 +280,7 @@ static void dio_bio_end_aio(struct bio *bio, int error) | |||
277 | spin_unlock_irqrestore(&dio->bio_lock, flags); | 280 | spin_unlock_irqrestore(&dio->bio_lock, flags); |
278 | 281 | ||
279 | if (remaining == 0) { | 282 | if (remaining == 0) { |
280 | int ret = dio_complete(dio, dio->iocb->ki_pos, 0); | 283 | dio_complete(dio, dio->iocb->ki_pos, 0, true); |
281 | aio_complete(dio->iocb, ret, 0); | ||
282 | kfree(dio); | 284 | kfree(dio); |
283 | } | 285 | } |
284 | } | 286 | } |
@@ -1126,7 +1128,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, | |||
1126 | spin_unlock_irqrestore(&dio->bio_lock, flags); | 1128 | spin_unlock_irqrestore(&dio->bio_lock, flags); |
1127 | 1129 | ||
1128 | if (ret2 == 0) { | 1130 | if (ret2 == 0) { |
1129 | ret = dio_complete(dio, offset, ret); | 1131 | ret = dio_complete(dio, offset, ret, false); |
1130 | kfree(dio); | 1132 | kfree(dio); |
1131 | } else | 1133 | } else |
1132 | BUG_ON(ret != -EIOCBQUEUED); | 1134 | BUG_ON(ret != -EIOCBQUEUED); |
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index c0d35c620526..37a34c2c622a 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c | |||
@@ -248,7 +248,7 @@ static struct connection *assoc2con(int assoc_id) | |||
248 | 248 | ||
249 | for (i = 0 ; i < CONN_HASH_SIZE; i++) { | 249 | for (i = 0 ; i < CONN_HASH_SIZE; i++) { |
250 | hlist_for_each_entry(con, h, &connection_hash[i], list) { | 250 | hlist_for_each_entry(con, h, &connection_hash[i], list) { |
251 | if (con && con->sctp_assoc == assoc_id) { | 251 | if (con->sctp_assoc == assoc_id) { |
252 | mutex_unlock(&connections_lock); | 252 | mutex_unlock(&connections_lock); |
253 | return con; | 253 | return con; |
254 | } | 254 | } |
diff --git a/fs/dlm/netlink.c b/fs/dlm/netlink.c index 2c6ad518100d..ef17e0169da1 100644 --- a/fs/dlm/netlink.c +++ b/fs/dlm/netlink.c | |||
@@ -81,24 +81,11 @@ static struct genl_ops dlm_nl_ops = { | |||
81 | 81 | ||
82 | int __init dlm_netlink_init(void) | 82 | int __init dlm_netlink_init(void) |
83 | { | 83 | { |
84 | int rv; | 84 | return genl_register_family_with_ops(&family, &dlm_nl_ops, 1); |
85 | |||
86 | rv = genl_register_family(&family); | ||
87 | if (rv) | ||
88 | return rv; | ||
89 | |||
90 | rv = genl_register_ops(&family, &dlm_nl_ops); | ||
91 | if (rv < 0) | ||
92 | goto err; | ||
93 | return 0; | ||
94 | err: | ||
95 | genl_unregister_family(&family); | ||
96 | return rv; | ||
97 | } | 85 | } |
98 | 86 | ||
99 | void dlm_netlink_exit(void) | 87 | void dlm_netlink_exit(void) |
100 | { | 88 | { |
101 | genl_unregister_ops(&family, &dlm_nl_ops); | ||
102 | genl_unregister_family(&family); | 89 | genl_unregister_family(&family); |
103 | } | 90 | } |
104 | 91 | ||
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 1cc087635a5e..a2e3b562e65d 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -762,7 +762,7 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, | |||
762 | 762 | ||
763 | /** | 763 | /** |
764 | * ecryptfs_init_crypt_ctx | 764 | * ecryptfs_init_crypt_ctx |
765 | * @crypt_stat: Uninitilized crypt stats structure | 765 | * @crypt_stat: Uninitialized crypt stats structure |
766 | * | 766 | * |
767 | * Initialize the crypto context. | 767 | * Initialize the crypto context. |
768 | * | 768 | * |
diff --git a/fs/ecryptfs/messaging.c b/fs/ecryptfs/messaging.c index 2d8dbce9d485..46c4dd8dfcc3 100644 --- a/fs/ecryptfs/messaging.c +++ b/fs/ecryptfs/messaging.c | |||
@@ -31,9 +31,9 @@ static struct mutex ecryptfs_msg_ctx_lists_mux; | |||
31 | 31 | ||
32 | static struct hlist_head *ecryptfs_daemon_hash; | 32 | static struct hlist_head *ecryptfs_daemon_hash; |
33 | struct mutex ecryptfs_daemon_hash_mux; | 33 | struct mutex ecryptfs_daemon_hash_mux; |
34 | static int ecryptfs_hash_buckets; | 34 | static int ecryptfs_hash_bits; |
35 | #define ecryptfs_uid_hash(uid) \ | 35 | #define ecryptfs_uid_hash(uid) \ |
36 | hash_long((unsigned long)uid, ecryptfs_hash_buckets) | 36 | hash_long((unsigned long)uid, ecryptfs_hash_bits) |
37 | 37 | ||
38 | static u32 ecryptfs_msg_counter; | 38 | static u32 ecryptfs_msg_counter; |
39 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; | 39 | static struct ecryptfs_msg_ctx *ecryptfs_msg_ctx_arr; |
@@ -486,18 +486,19 @@ int ecryptfs_init_messaging(void) | |||
486 | } | 486 | } |
487 | mutex_init(&ecryptfs_daemon_hash_mux); | 487 | mutex_init(&ecryptfs_daemon_hash_mux); |
488 | mutex_lock(&ecryptfs_daemon_hash_mux); | 488 | mutex_lock(&ecryptfs_daemon_hash_mux); |
489 | ecryptfs_hash_buckets = 1; | 489 | ecryptfs_hash_bits = 1; |
490 | while (ecryptfs_number_of_users >> ecryptfs_hash_buckets) | 490 | while (ecryptfs_number_of_users >> ecryptfs_hash_bits) |
491 | ecryptfs_hash_buckets++; | 491 | ecryptfs_hash_bits++; |
492 | ecryptfs_daemon_hash = kmalloc((sizeof(struct hlist_head) | 492 | ecryptfs_daemon_hash = kmalloc((sizeof(struct hlist_head) |
493 | * ecryptfs_hash_buckets), GFP_KERNEL); | 493 | * (1 << ecryptfs_hash_bits)), |
494 | GFP_KERNEL); | ||
494 | if (!ecryptfs_daemon_hash) { | 495 | if (!ecryptfs_daemon_hash) { |
495 | rc = -ENOMEM; | 496 | rc = -ENOMEM; |
496 | printk(KERN_ERR "%s: Failed to allocate memory\n", __func__); | 497 | printk(KERN_ERR "%s: Failed to allocate memory\n", __func__); |
497 | mutex_unlock(&ecryptfs_daemon_hash_mux); | 498 | mutex_unlock(&ecryptfs_daemon_hash_mux); |
498 | goto out; | 499 | goto out; |
499 | } | 500 | } |
500 | for (i = 0; i < ecryptfs_hash_buckets; i++) | 501 | for (i = 0; i < (1 << ecryptfs_hash_bits); i++) |
501 | INIT_HLIST_HEAD(&ecryptfs_daemon_hash[i]); | 502 | INIT_HLIST_HEAD(&ecryptfs_daemon_hash[i]); |
502 | mutex_unlock(&ecryptfs_daemon_hash_mux); | 503 | mutex_unlock(&ecryptfs_daemon_hash_mux); |
503 | ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx) | 504 | ecryptfs_msg_ctx_arr = kmalloc((sizeof(struct ecryptfs_msg_ctx) |
@@ -554,7 +555,7 @@ void ecryptfs_release_messaging(void) | |||
554 | int i; | 555 | int i; |
555 | 556 | ||
556 | mutex_lock(&ecryptfs_daemon_hash_mux); | 557 | mutex_lock(&ecryptfs_daemon_hash_mux); |
557 | for (i = 0; i < ecryptfs_hash_buckets; i++) { | 558 | for (i = 0; i < (1 << ecryptfs_hash_bits); i++) { |
558 | int rc; | 559 | int rc; |
559 | 560 | ||
560 | hlist_for_each_entry(daemon, elem, | 561 | hlist_for_each_entry(daemon, elem, |
@@ -28,7 +28,6 @@ | |||
28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/stat.h> | 29 | #include <linux/stat.h> |
30 | #include <linux/fcntl.h> | 30 | #include <linux/fcntl.h> |
31 | #include <linux/smp_lock.h> | ||
32 | #include <linux/swap.h> | 31 | #include <linux/swap.h> |
33 | #include <linux/string.h> | 32 | #include <linux/string.h> |
34 | #include <linux/init.h> | 33 | #include <linux/init.h> |
@@ -653,6 +652,7 @@ int setup_arg_pages(struct linux_binprm *bprm, | |||
653 | else | 652 | else |
654 | stack_base = vma->vm_start - stack_expand; | 653 | stack_base = vma->vm_start - stack_expand; |
655 | #endif | 654 | #endif |
655 | current->mm->start_stack = bprm->p; | ||
656 | ret = expand_stack(vma, stack_base); | 656 | ret = expand_stack(vma, stack_base); |
657 | if (ret) | 657 | if (ret) |
658 | ret = -EFAULT; | 658 | ret = -EFAULT; |
@@ -1891,13 +1891,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) | |||
1891 | */ | 1891 | */ |
1892 | clear_thread_flag(TIF_SIGPENDING); | 1892 | clear_thread_flag(TIF_SIGPENDING); |
1893 | 1893 | ||
1894 | /* | ||
1895 | * lock_kernel() because format_corename() is controlled by sysctl, which | ||
1896 | * uses lock_kernel() | ||
1897 | */ | ||
1898 | lock_kernel(); | ||
1899 | ispipe = format_corename(corename, signr); | 1894 | ispipe = format_corename(corename, signr); |
1900 | unlock_kernel(); | ||
1901 | 1895 | ||
1902 | if (ispipe) { | 1896 | if (ispipe) { |
1903 | int dump_count; | 1897 | int dump_count; |
diff --git a/fs/ext3/Kconfig b/fs/ext3/Kconfig index 522b15498f45..e8c6ba0e4a3e 100644 --- a/fs/ext3/Kconfig +++ b/fs/ext3/Kconfig | |||
@@ -31,6 +31,7 @@ config EXT3_FS | |||
31 | config EXT3_DEFAULTS_TO_ORDERED | 31 | config EXT3_DEFAULTS_TO_ORDERED |
32 | bool "Default to 'data=ordered' in ext3" | 32 | bool "Default to 'data=ordered' in ext3" |
33 | depends on EXT3_FS | 33 | depends on EXT3_FS |
34 | default y | ||
34 | help | 35 | help |
35 | The journal mode options for ext3 have different tradeoffs | 36 | The journal mode options for ext3 have different tradeoffs |
36 | between when data is guaranteed to be on disk and | 37 | between when data is guaranteed to be on disk and |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 735f0190ec2a..001eb0e2d48e 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -1149,9 +1149,25 @@ static int walk_page_buffers( handle_t *handle, | |||
1149 | static int do_journal_get_write_access(handle_t *handle, | 1149 | static int do_journal_get_write_access(handle_t *handle, |
1150 | struct buffer_head *bh) | 1150 | struct buffer_head *bh) |
1151 | { | 1151 | { |
1152 | int dirty = buffer_dirty(bh); | ||
1153 | int ret; | ||
1154 | |||
1152 | if (!buffer_mapped(bh) || buffer_freed(bh)) | 1155 | if (!buffer_mapped(bh) || buffer_freed(bh)) |
1153 | return 0; | 1156 | return 0; |
1154 | return ext3_journal_get_write_access(handle, bh); | 1157 | /* |
1158 | * __block_prepare_write() could have dirtied some buffers. Clean | ||
1159 | * the dirty bit as jbd2_journal_get_write_access() could complain | ||
1160 | * otherwise about fs integrity issues. Setting of the dirty bit | ||
1161 | * by __block_prepare_write() isn't a real problem here as we clear | ||
1162 | * the bit before releasing a page lock and thus writeback cannot | ||
1163 | * ever write the buffer. | ||
1164 | */ | ||
1165 | if (dirty) | ||
1166 | clear_buffer_dirty(bh); | ||
1167 | ret = ext3_journal_get_write_access(handle, bh); | ||
1168 | if (!ret && dirty) | ||
1169 | ret = ext3_journal_dirty_metadata(handle, bh); | ||
1170 | return ret; | ||
1155 | } | 1171 | } |
1156 | 1172 | ||
1157 | /* | 1173 | /* |
@@ -1625,10 +1641,7 @@ static int ext3_writeback_writepage(struct page *page, | |||
1625 | goto out_fail; | 1641 | goto out_fail; |
1626 | } | 1642 | } |
1627 | 1643 | ||
1628 | if (test_opt(inode->i_sb, NOBH) && ext3_should_writeback_data(inode)) | 1644 | ret = block_write_full_page(page, ext3_get_block, wbc); |
1629 | ret = nobh_writepage(page, ext3_get_block, wbc); | ||
1630 | else | ||
1631 | ret = block_write_full_page(page, ext3_get_block, wbc); | ||
1632 | 1645 | ||
1633 | err = ext3_journal_stop(handle); | 1646 | err = ext3_journal_stop(handle); |
1634 | if (!ret) | 1647 | if (!ret) |
@@ -1922,17 +1935,6 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page, | |||
1922 | length = blocksize - (offset & (blocksize - 1)); | 1935 | length = blocksize - (offset & (blocksize - 1)); |
1923 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); | 1936 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); |
1924 | 1937 | ||
1925 | /* | ||
1926 | * For "nobh" option, we can only work if we don't need to | ||
1927 | * read-in the page - otherwise we create buffers to do the IO. | ||
1928 | */ | ||
1929 | if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) && | ||
1930 | ext3_should_writeback_data(inode) && PageUptodate(page)) { | ||
1931 | zero_user(page, offset, length); | ||
1932 | set_page_dirty(page); | ||
1933 | goto unlock; | ||
1934 | } | ||
1935 | |||
1936 | if (!page_has_buffers(page)) | 1938 | if (!page_has_buffers(page)) |
1937 | create_empty_buffers(page, blocksize, 0); | 1939 | create_empty_buffers(page, blocksize, 0); |
1938 | 1940 | ||
@@ -2284,27 +2286,6 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode, | |||
2284 | depth); | 2286 | depth); |
2285 | 2287 | ||
2286 | /* | 2288 | /* |
2287 | * We've probably journalled the indirect block several | ||
2288 | * times during the truncate. But it's no longer | ||
2289 | * needed and we now drop it from the transaction via | ||
2290 | * journal_revoke(). | ||
2291 | * | ||
2292 | * That's easy if it's exclusively part of this | ||
2293 | * transaction. But if it's part of the committing | ||
2294 | * transaction then journal_forget() will simply | ||
2295 | * brelse() it. That means that if the underlying | ||
2296 | * block is reallocated in ext3_get_block(), | ||
2297 | * unmap_underlying_metadata() will find this block | ||
2298 | * and will try to get rid of it. damn, damn. | ||
2299 | * | ||
2300 | * If this block has already been committed to the | ||
2301 | * journal, a revoke record will be written. And | ||
2302 | * revoke records must be emitted *before* clearing | ||
2303 | * this block's bit in the bitmaps. | ||
2304 | */ | ||
2305 | ext3_forget(handle, 1, inode, bh, bh->b_blocknr); | ||
2306 | |||
2307 | /* | ||
2308 | * Everything below this this pointer has been | 2289 | * Everything below this this pointer has been |
2309 | * released. Now let this top-of-subtree go. | 2290 | * released. Now let this top-of-subtree go. |
2310 | * | 2291 | * |
@@ -2327,6 +2308,31 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode, | |||
2327 | truncate_restart_transaction(handle, inode); | 2308 | truncate_restart_transaction(handle, inode); |
2328 | } | 2309 | } |
2329 | 2310 | ||
2311 | /* | ||
2312 | * We've probably journalled the indirect block several | ||
2313 | * times during the truncate. But it's no longer | ||
2314 | * needed and we now drop it from the transaction via | ||
2315 | * journal_revoke(). | ||
2316 | * | ||
2317 | * That's easy if it's exclusively part of this | ||
2318 | * transaction. But if it's part of the committing | ||
2319 | * transaction then journal_forget() will simply | ||
2320 | * brelse() it. That means that if the underlying | ||
2321 | * block is reallocated in ext3_get_block(), | ||
2322 | * unmap_underlying_metadata() will find this block | ||
2323 | * and will try to get rid of it. damn, damn. Thus | ||
2324 | * we don't allow a block to be reallocated until | ||
2325 | * a transaction freeing it has fully committed. | ||
2326 | * | ||
2327 | * We also have to make sure journal replay after a | ||
2328 | * crash does not overwrite non-journaled data blocks | ||
2329 | * with old metadata when the block got reallocated for | ||
2330 | * data. Thus we have to store a revoke record for a | ||
2331 | * block in the same transaction in which we free the | ||
2332 | * block. | ||
2333 | */ | ||
2334 | ext3_forget(handle, 1, inode, bh, bh->b_blocknr); | ||
2335 | |||
2330 | ext3_free_blocks(handle, inode, nr, 1); | 2336 | ext3_free_blocks(handle, inode, nr, 1); |
2331 | 2337 | ||
2332 | if (parent_bh) { | 2338 | if (parent_bh) { |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index ee184084ca42..2b35ddb70d65 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
@@ -1447,7 +1447,6 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry, | |||
1447 | struct inode *inode) | 1447 | struct inode *inode) |
1448 | { | 1448 | { |
1449 | struct inode *dir = dentry->d_parent->d_inode; | 1449 | struct inode *dir = dentry->d_parent->d_inode; |
1450 | unsigned long offset; | ||
1451 | struct buffer_head * bh; | 1450 | struct buffer_head * bh; |
1452 | struct ext3_dir_entry_2 *de; | 1451 | struct ext3_dir_entry_2 *de; |
1453 | struct super_block * sb; | 1452 | struct super_block * sb; |
@@ -1469,7 +1468,7 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry, | |||
1469 | ext3_mark_inode_dirty(handle, dir); | 1468 | ext3_mark_inode_dirty(handle, dir); |
1470 | } | 1469 | } |
1471 | blocks = dir->i_size >> sb->s_blocksize_bits; | 1470 | blocks = dir->i_size >> sb->s_blocksize_bits; |
1472 | for (block = 0, offset = 0; block < blocks; block++) { | 1471 | for (block = 0; block < blocks; block++) { |
1473 | bh = ext3_bread(handle, dir, block, 0, &retval); | 1472 | bh = ext3_bread(handle, dir, block, 0, &retval); |
1474 | if(!bh) | 1473 | if(!bh) |
1475 | return retval; | 1474 | return retval; |
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 54351ac7cef9..0ccd7b12b73c 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c | |||
@@ -964,7 +964,6 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, | |||
964 | ext3_fsblk_t n_blocks_count) | 964 | ext3_fsblk_t n_blocks_count) |
965 | { | 965 | { |
966 | ext3_fsblk_t o_blocks_count; | 966 | ext3_fsblk_t o_blocks_count; |
967 | unsigned long o_groups_count; | ||
968 | ext3_grpblk_t last; | 967 | ext3_grpblk_t last; |
969 | ext3_grpblk_t add; | 968 | ext3_grpblk_t add; |
970 | struct buffer_head * bh; | 969 | struct buffer_head * bh; |
@@ -976,7 +975,6 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, | |||
976 | * yet: we're going to revalidate es->s_blocks_count after | 975 | * yet: we're going to revalidate es->s_blocks_count after |
977 | * taking the s_resize_lock below. */ | 976 | * taking the s_resize_lock below. */ |
978 | o_blocks_count = le32_to_cpu(es->s_blocks_count); | 977 | o_blocks_count = le32_to_cpu(es->s_blocks_count); |
979 | o_groups_count = EXT3_SB(sb)->s_groups_count; | ||
980 | 978 | ||
981 | if (test_opt(sb, DEBUG)) | 979 | if (test_opt(sb, DEBUG)) |
982 | printk(KERN_DEBUG "EXT3-fs: extending last group from "E3FSBLK" uto "E3FSBLK" blocks\n", | 980 | printk(KERN_DEBUG "EXT3-fs: extending last group from "E3FSBLK" uto "E3FSBLK" blocks\n", |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 6c953bb255e7..9650a956fd0e 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -661,9 +661,6 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
661 | */ | 661 | */ |
662 | seq_puts(seq, ",barrier="); | 662 | seq_puts(seq, ",barrier="); |
663 | seq_puts(seq, test_opt(sb, BARRIER) ? "1" : "0"); | 663 | seq_puts(seq, test_opt(sb, BARRIER) ? "1" : "0"); |
664 | if (test_opt(sb, NOBH)) | ||
665 | seq_puts(seq, ",nobh"); | ||
666 | |||
667 | seq_printf(seq, ",data=%s", data_mode_string(test_opt(sb, DATA_FLAGS))); | 664 | seq_printf(seq, ",data=%s", data_mode_string(test_opt(sb, DATA_FLAGS))); |
668 | if (test_opt(sb, DATA_ERR_ABORT)) | 665 | if (test_opt(sb, DATA_ERR_ABORT)) |
669 | seq_puts(seq, ",data_err=abort"); | 666 | seq_puts(seq, ",data_err=abort"); |
@@ -1255,10 +1252,12 @@ set_qf_format: | |||
1255 | *n_blocks_count = option; | 1252 | *n_blocks_count = option; |
1256 | break; | 1253 | break; |
1257 | case Opt_nobh: | 1254 | case Opt_nobh: |
1258 | set_opt(sbi->s_mount_opt, NOBH); | 1255 | ext3_msg(sb, KERN_WARNING, |
1256 | "warning: ignoring deprecated nobh option"); | ||
1259 | break; | 1257 | break; |
1260 | case Opt_bh: | 1258 | case Opt_bh: |
1261 | clear_opt(sbi->s_mount_opt, NOBH); | 1259 | ext3_msg(sb, KERN_WARNING, |
1260 | "warning: ignoring deprecated bh option"); | ||
1262 | break; | 1261 | break; |
1263 | default: | 1262 | default: |
1264 | ext3_msg(sb, KERN_ERR, | 1263 | ext3_msg(sb, KERN_ERR, |
@@ -2001,14 +2000,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
2001 | break; | 2000 | break; |
2002 | } | 2001 | } |
2003 | 2002 | ||
2004 | if (test_opt(sb, NOBH)) { | ||
2005 | if (!(test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)) { | ||
2006 | ext3_msg(sb, KERN_WARNING, | ||
2007 | "warning: ignoring nobh option - " | ||
2008 | "it is supported only with writeback mode"); | ||
2009 | clear_opt(sbi->s_mount_opt, NOBH); | ||
2010 | } | ||
2011 | } | ||
2012 | /* | 2003 | /* |
2013 | * The journal_load will have done any necessary log recovery, | 2004 | * The journal_load will have done any necessary log recovery, |
2014 | * so we can safely mount the rest of the filesystem now. | 2005 | * so we can safely mount the rest of the filesystem now. |
diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index feaf498feaa6..5e2ed4504ead 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c | |||
@@ -204,6 +204,7 @@ ext4_set_acl(handle_t *handle, struct inode *inode, int type, | |||
204 | return error; | 204 | return error; |
205 | else { | 205 | else { |
206 | inode->i_mode = mode; | 206 | inode->i_mode = mode; |
207 | inode->i_ctime = ext4_current_time(inode); | ||
207 | ext4_mark_inode_dirty(handle, inode); | 208 | ext4_mark_inode_dirty(handle, inode); |
208 | if (error == 0) | 209 | if (error == 0) |
209 | acl = NULL; | 210 | acl = NULL; |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 95b7594c76f9..bd30799a43ed 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
@@ -377,14 +377,11 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, | |||
377 | ext4_grpblk_t bit; | 377 | ext4_grpblk_t bit; |
378 | unsigned int i; | 378 | unsigned int i; |
379 | struct ext4_group_desc *desc; | 379 | struct ext4_group_desc *desc; |
380 | struct ext4_super_block *es; | 380 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
381 | struct ext4_sb_info *sbi; | ||
382 | int err = 0, ret, blk_free_count; | 381 | int err = 0, ret, blk_free_count; |
383 | ext4_grpblk_t blocks_freed; | 382 | ext4_grpblk_t blocks_freed; |
384 | struct ext4_group_info *grp; | 383 | struct ext4_group_info *grp; |
385 | 384 | ||
386 | sbi = EXT4_SB(sb); | ||
387 | es = sbi->s_es; | ||
388 | ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1); | 385 | ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1); |
389 | 386 | ||
390 | ext4_get_group_no_and_offset(sb, block, &block_group, &bit); | 387 | ext4_get_group_no_and_offset(sb, block, &block_group, &bit); |
@@ -477,7 +474,6 @@ void ext4_add_groupblocks(handle_t *handle, struct super_block *sb, | |||
477 | ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh); | 474 | ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh); |
478 | if (!err) | 475 | if (!err) |
479 | err = ret; | 476 | err = ret; |
480 | sb->s_dirt = 1; | ||
481 | 477 | ||
482 | error_return: | 478 | error_return: |
483 | brelse(bitmap_bh); | 479 | brelse(bitmap_bh); |
diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c index 5b6973fbf1bd..3db5084db9bd 100644 --- a/fs/ext4/block_validity.c +++ b/fs/ext4/block_validity.c | |||
@@ -229,16 +229,20 @@ int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk, | |||
229 | 229 | ||
230 | if ((start_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) || | 230 | if ((start_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) || |
231 | (start_blk + count < start_blk) || | 231 | (start_blk + count < start_blk) || |
232 | (start_blk + count > ext4_blocks_count(sbi->s_es))) | 232 | (start_blk + count > ext4_blocks_count(sbi->s_es))) { |
233 | sbi->s_es->s_last_error_block = cpu_to_le64(start_blk); | ||
233 | return 0; | 234 | return 0; |
235 | } | ||
234 | while (n) { | 236 | while (n) { |
235 | entry = rb_entry(n, struct ext4_system_zone, node); | 237 | entry = rb_entry(n, struct ext4_system_zone, node); |
236 | if (start_blk + count - 1 < entry->start_blk) | 238 | if (start_blk + count - 1 < entry->start_blk) |
237 | n = n->rb_left; | 239 | n = n->rb_left; |
238 | else if (start_blk >= (entry->start_blk + entry->count)) | 240 | else if (start_blk >= (entry->start_blk + entry->count)) |
239 | n = n->rb_right; | 241 | n = n->rb_right; |
240 | else | 242 | else { |
243 | sbi->s_es->s_last_error_block = cpu_to_le64(start_blk); | ||
241 | return 0; | 244 | return 0; |
245 | } | ||
242 | } | 246 | } |
243 | return 1; | 247 | return 1; |
244 | } | 248 | } |
diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index ea5e6cb7e2a5..374510f72baa 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c | |||
@@ -61,10 +61,11 @@ static unsigned char get_dtype(struct super_block *sb, int filetype) | |||
61 | } | 61 | } |
62 | 62 | ||
63 | 63 | ||
64 | int ext4_check_dir_entry(const char *function, struct inode *dir, | 64 | int __ext4_check_dir_entry(const char *function, unsigned int line, |
65 | struct ext4_dir_entry_2 *de, | 65 | struct inode *dir, |
66 | struct buffer_head *bh, | 66 | struct ext4_dir_entry_2 *de, |
67 | unsigned int offset) | 67 | struct buffer_head *bh, |
68 | unsigned int offset) | ||
68 | { | 69 | { |
69 | const char *error_msg = NULL; | 70 | const char *error_msg = NULL; |
70 | const int rlen = ext4_rec_len_from_disk(de->rec_len, | 71 | const int rlen = ext4_rec_len_from_disk(de->rec_len, |
@@ -83,11 +84,10 @@ int ext4_check_dir_entry(const char *function, struct inode *dir, | |||
83 | error_msg = "inode out of bounds"; | 84 | error_msg = "inode out of bounds"; |
84 | 85 | ||
85 | if (error_msg != NULL) | 86 | if (error_msg != NULL) |
86 | ext4_error_inode(function, dir, | 87 | ext4_error_inode(dir, function, line, bh->b_blocknr, |
87 | "bad entry in directory: %s - block=%llu" | 88 | "bad entry in directory: %s - " |
88 | "offset=%u(%u), inode=%u, rec_len=%d, name_len=%d", | 89 | "offset=%u(%u), inode=%u, rec_len=%d, name_len=%d", |
89 | error_msg, (unsigned long long) bh->b_blocknr, | 90 | error_msg, (unsigned) (offset%bh->b_size), offset, |
90 | (unsigned) (offset%bh->b_size), offset, | ||
91 | le32_to_cpu(de->inode), | 91 | le32_to_cpu(de->inode), |
92 | rlen, de->name_len); | 92 | rlen, de->name_len); |
93 | return error_msg == NULL ? 1 : 0; | 93 | return error_msg == NULL ? 1 : 0; |
@@ -121,7 +121,8 @@ static int ext4_readdir(struct file *filp, | |||
121 | * We don't set the inode dirty flag since it's not | 121 | * We don't set the inode dirty flag since it's not |
122 | * critical that it get flushed back to the disk. | 122 | * critical that it get flushed back to the disk. |
123 | */ | 123 | */ |
124 | ext4_clear_inode_flag(filp->f_path.dentry->d_inode, EXT4_INODE_INDEX); | 124 | ext4_clear_inode_flag(filp->f_path.dentry->d_inode, |
125 | EXT4_INODE_INDEX); | ||
125 | } | 126 | } |
126 | stored = 0; | 127 | stored = 0; |
127 | offset = filp->f_pos & (sb->s_blocksize - 1); | 128 | offset = filp->f_pos & (sb->s_blocksize - 1); |
@@ -193,7 +194,7 @@ revalidate: | |||
193 | while (!error && filp->f_pos < inode->i_size | 194 | while (!error && filp->f_pos < inode->i_size |
194 | && offset < sb->s_blocksize) { | 195 | && offset < sb->s_blocksize) { |
195 | de = (struct ext4_dir_entry_2 *) (bh->b_data + offset); | 196 | de = (struct ext4_dir_entry_2 *) (bh->b_data + offset); |
196 | if (!ext4_check_dir_entry("ext4_readdir", inode, de, | 197 | if (!ext4_check_dir_entry(inode, de, |
197 | bh, offset)) { | 198 | bh, offset)) { |
198 | /* | 199 | /* |
199 | * On error, skip the f_pos to the next block | 200 | * On error, skip the f_pos to the next block |
@@ -343,7 +344,7 @@ int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, | |||
343 | struct dir_private_info *info; | 344 | struct dir_private_info *info; |
344 | int len; | 345 | int len; |
345 | 346 | ||
346 | info = (struct dir_private_info *) dir_file->private_data; | 347 | info = dir_file->private_data; |
347 | p = &info->root.rb_node; | 348 | p = &info->root.rb_node; |
348 | 349 | ||
349 | /* Create and allocate the fname structure */ | 350 | /* Create and allocate the fname structure */ |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 19a4de57128a..e03841d9f30b 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -57,10 +57,13 @@ | |||
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | #define EXT4_ERROR_INODE(inode, fmt, a...) \ | 59 | #define EXT4_ERROR_INODE(inode, fmt, a...) \ |
60 | ext4_error_inode(__func__, (inode), (fmt), ## a) | 60 | ext4_error_inode((inode), __func__, __LINE__, 0, (fmt), ## a) |
61 | |||
62 | #define EXT4_ERROR_INODE_BLOCK(inode, block, fmt, a...) \ | ||
63 | ext4_error_inode((inode), __func__, __LINE__, (block), (fmt), ## a) | ||
61 | 64 | ||
62 | #define EXT4_ERROR_FILE(file, fmt, a...) \ | 65 | #define EXT4_ERROR_FILE(file, fmt, a...) \ |
63 | ext4_error_file(__func__, (file), (fmt), ## a) | 66 | ext4_error_file(__func__, __LINE__, (file), (fmt), ## a) |
64 | 67 | ||
65 | /* data type for block offset of block group */ | 68 | /* data type for block offset of block group */ |
66 | typedef int ext4_grpblk_t; | 69 | typedef int ext4_grpblk_t; |
@@ -167,13 +170,15 @@ struct mpage_da_data { | |||
167 | }; | 170 | }; |
168 | #define EXT4_IO_UNWRITTEN 0x1 | 171 | #define EXT4_IO_UNWRITTEN 0x1 |
169 | typedef struct ext4_io_end { | 172 | typedef struct ext4_io_end { |
170 | struct list_head list; /* per-file finished AIO list */ | 173 | struct list_head list; /* per-file finished IO list */ |
171 | struct inode *inode; /* file being written to */ | 174 | struct inode *inode; /* file being written to */ |
172 | unsigned int flag; /* unwritten or not */ | 175 | unsigned int flag; /* unwritten or not */ |
173 | struct page *page; /* page struct for buffer write */ | 176 | struct page *page; /* page struct for buffer write */ |
174 | loff_t offset; /* offset in the file */ | 177 | loff_t offset; /* offset in the file */ |
175 | ssize_t size; /* size of the extent */ | 178 | ssize_t size; /* size of the extent */ |
176 | struct work_struct work; /* data work queue */ | 179 | struct work_struct work; /* data work queue */ |
180 | struct kiocb *iocb; /* iocb struct for AIO */ | ||
181 | int result; /* error value for AIO */ | ||
177 | } ext4_io_end_t; | 182 | } ext4_io_end_t; |
178 | 183 | ||
179 | /* | 184 | /* |
@@ -460,7 +465,7 @@ struct ext4_new_group_data { | |||
460 | }; | 465 | }; |
461 | 466 | ||
462 | /* | 467 | /* |
463 | * Flags used by ext4_get_blocks() | 468 | * Flags used by ext4_map_blocks() |
464 | */ | 469 | */ |
465 | /* Allocate any needed blocks and/or convert an unitialized | 470 | /* Allocate any needed blocks and/or convert an unitialized |
466 | extent to be an initialized ext4 */ | 471 | extent to be an initialized ext4 */ |
@@ -873,7 +878,6 @@ struct ext4_inode_info { | |||
873 | #define EXT4_MOUNT_POSIX_ACL 0x08000 /* POSIX Access Control Lists */ | 878 | #define EXT4_MOUNT_POSIX_ACL 0x08000 /* POSIX Access Control Lists */ |
874 | #define EXT4_MOUNT_NO_AUTO_DA_ALLOC 0x10000 /* No auto delalloc mapping */ | 879 | #define EXT4_MOUNT_NO_AUTO_DA_ALLOC 0x10000 /* No auto delalloc mapping */ |
875 | #define EXT4_MOUNT_BARRIER 0x20000 /* Use block barriers */ | 880 | #define EXT4_MOUNT_BARRIER 0x20000 /* Use block barriers */ |
876 | #define EXT4_MOUNT_NOBH 0x40000 /* No bufferheads */ | ||
877 | #define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */ | 881 | #define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */ |
878 | #define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */ | 882 | #define EXT4_MOUNT_USRQUOTA 0x100000 /* "old" user quota */ |
879 | #define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */ | 883 | #define EXT4_MOUNT_GRPQUOTA 0x200000 /* "old" group quota */ |
@@ -982,7 +986,7 @@ struct ext4_super_block { | |||
982 | __le32 s_last_orphan; /* start of list of inodes to delete */ | 986 | __le32 s_last_orphan; /* start of list of inodes to delete */ |
983 | __le32 s_hash_seed[4]; /* HTREE hash seed */ | 987 | __le32 s_hash_seed[4]; /* HTREE hash seed */ |
984 | __u8 s_def_hash_version; /* Default hash version to use */ | 988 | __u8 s_def_hash_version; /* Default hash version to use */ |
985 | __u8 s_reserved_char_pad; | 989 | __u8 s_jnl_backup_type; |
986 | __le16 s_desc_size; /* size of group descriptor */ | 990 | __le16 s_desc_size; /* size of group descriptor */ |
987 | /*100*/ __le32 s_default_mount_opts; | 991 | /*100*/ __le32 s_default_mount_opts; |
988 | __le32 s_first_meta_bg; /* First metablock block group */ | 992 | __le32 s_first_meta_bg; /* First metablock block group */ |
@@ -1000,12 +1004,34 @@ struct ext4_super_block { | |||
1000 | __le64 s_mmp_block; /* Block for multi-mount protection */ | 1004 | __le64 s_mmp_block; /* Block for multi-mount protection */ |
1001 | __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ | 1005 | __le32 s_raid_stripe_width; /* blocks on all data disks (N*stride)*/ |
1002 | __u8 s_log_groups_per_flex; /* FLEX_BG group size */ | 1006 | __u8 s_log_groups_per_flex; /* FLEX_BG group size */ |
1003 | __u8 s_reserved_char_pad2; | 1007 | __u8 s_reserved_char_pad; |
1004 | __le16 s_reserved_pad; | 1008 | __le16 s_reserved_pad; |
1005 | __le64 s_kbytes_written; /* nr of lifetime kilobytes written */ | 1009 | __le64 s_kbytes_written; /* nr of lifetime kilobytes written */ |
1006 | __u32 s_reserved[160]; /* Padding to the end of the block */ | 1010 | __le32 s_snapshot_inum; /* Inode number of active snapshot */ |
1011 | __le32 s_snapshot_id; /* sequential ID of active snapshot */ | ||
1012 | __le64 s_snapshot_r_blocks_count; /* reserved blocks for active | ||
1013 | snapshot's future use */ | ||
1014 | __le32 s_snapshot_list; /* inode number of the head of the | ||
1015 | on-disk snapshot list */ | ||
1016 | #define EXT4_S_ERR_START offsetof(struct ext4_super_block, s_error_count) | ||
1017 | __le32 s_error_count; /* number of fs errors */ | ||
1018 | __le32 s_first_error_time; /* first time an error happened */ | ||
1019 | __le32 s_first_error_ino; /* inode involved in first error */ | ||
1020 | __le64 s_first_error_block; /* block involved of first error */ | ||
1021 | __u8 s_first_error_func[32]; /* function where the error happened */ | ||
1022 | __le32 s_first_error_line; /* line number where error happened */ | ||
1023 | __le32 s_last_error_time; /* most recent time of an error */ | ||
1024 | __le32 s_last_error_ino; /* inode involved in last error */ | ||
1025 | __le32 s_last_error_line; /* line number where error happened */ | ||
1026 | __le64 s_last_error_block; /* block involved of last error */ | ||
1027 | __u8 s_last_error_func[32]; /* function where the error happened */ | ||
1028 | #define EXT4_S_ERR_END offsetof(struct ext4_super_block, s_mount_opts) | ||
1029 | __u8 s_mount_opts[64]; | ||
1030 | __le32 s_reserved[112]; /* Padding to the end of the block */ | ||
1007 | }; | 1031 | }; |
1008 | 1032 | ||
1033 | #define EXT4_S_ERR_LEN (EXT4_S_ERR_END - EXT4_S_ERR_START) | ||
1034 | |||
1009 | #ifdef __KERNEL__ | 1035 | #ifdef __KERNEL__ |
1010 | 1036 | ||
1011 | /* | 1037 | /* |
@@ -1143,6 +1169,9 @@ struct ext4_sb_info { | |||
1143 | 1169 | ||
1144 | /* workqueue for dio unwritten */ | 1170 | /* workqueue for dio unwritten */ |
1145 | struct workqueue_struct *dio_unwritten_wq; | 1171 | struct workqueue_struct *dio_unwritten_wq; |
1172 | |||
1173 | /* timer for periodic error stats printing */ | ||
1174 | struct timer_list s_err_report; | ||
1146 | }; | 1175 | }; |
1147 | 1176 | ||
1148 | static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) | 1177 | static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb) |
@@ -1313,6 +1342,10 @@ EXT4_INODE_BIT_FNS(state, state_flags) | |||
1313 | #define EXT4_DEFM_JMODE_DATA 0x0020 | 1342 | #define EXT4_DEFM_JMODE_DATA 0x0020 |
1314 | #define EXT4_DEFM_JMODE_ORDERED 0x0040 | 1343 | #define EXT4_DEFM_JMODE_ORDERED 0x0040 |
1315 | #define EXT4_DEFM_JMODE_WBACK 0x0060 | 1344 | #define EXT4_DEFM_JMODE_WBACK 0x0060 |
1345 | #define EXT4_DEFM_NOBARRIER 0x0100 | ||
1346 | #define EXT4_DEFM_BLOCK_VALIDITY 0x0200 | ||
1347 | #define EXT4_DEFM_DISCARD 0x0400 | ||
1348 | #define EXT4_DEFM_NODELALLOC 0x0800 | ||
1316 | 1349 | ||
1317 | /* | 1350 | /* |
1318 | * Default journal batch times | 1351 | * Default journal batch times |
@@ -1379,6 +1412,43 @@ struct ext4_dir_entry_2 { | |||
1379 | #define EXT4_MAX_REC_LEN ((1<<16)-1) | 1412 | #define EXT4_MAX_REC_LEN ((1<<16)-1) |
1380 | 1413 | ||
1381 | /* | 1414 | /* |
1415 | * If we ever get support for fs block sizes > page_size, we'll need | ||
1416 | * to remove the #if statements in the next two functions... | ||
1417 | */ | ||
1418 | static inline unsigned int | ||
1419 | ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize) | ||
1420 | { | ||
1421 | unsigned len = le16_to_cpu(dlen); | ||
1422 | |||
1423 | #if (PAGE_CACHE_SIZE >= 65536) | ||
1424 | if (len == EXT4_MAX_REC_LEN || len == 0) | ||
1425 | return blocksize; | ||
1426 | return (len & 65532) | ((len & 3) << 16); | ||
1427 | #else | ||
1428 | return len; | ||
1429 | #endif | ||
1430 | } | ||
1431 | |||
1432 | static inline __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize) | ||
1433 | { | ||
1434 | if ((len > blocksize) || (blocksize > (1 << 18)) || (len & 3)) | ||
1435 | BUG(); | ||
1436 | #if (PAGE_CACHE_SIZE >= 65536) | ||
1437 | if (len < 65536) | ||
1438 | return cpu_to_le16(len); | ||
1439 | if (len == blocksize) { | ||
1440 | if (blocksize == 65536) | ||
1441 | return cpu_to_le16(EXT4_MAX_REC_LEN); | ||
1442 | else | ||
1443 | return cpu_to_le16(0); | ||
1444 | } | ||
1445 | return cpu_to_le16((len & 65532) | ((len >> 16) & 3)); | ||
1446 | #else | ||
1447 | return cpu_to_le16(len); | ||
1448 | #endif | ||
1449 | } | ||
1450 | |||
1451 | /* | ||
1382 | * Hash Tree Directory indexing | 1452 | * Hash Tree Directory indexing |
1383 | * (c) Daniel Phillips, 2001 | 1453 | * (c) Daniel Phillips, 2001 |
1384 | */ | 1454 | */ |
@@ -1510,9 +1580,11 @@ extern unsigned ext4_init_block_bitmap(struct super_block *sb, | |||
1510 | ext4_init_block_bitmap(sb, NULL, group, desc) | 1580 | ext4_init_block_bitmap(sb, NULL, group, desc) |
1511 | 1581 | ||
1512 | /* dir.c */ | 1582 | /* dir.c */ |
1513 | extern int ext4_check_dir_entry(const char *, struct inode *, | 1583 | extern int __ext4_check_dir_entry(const char *, unsigned int, struct inode *, |
1514 | struct ext4_dir_entry_2 *, | 1584 | struct ext4_dir_entry_2 *, |
1515 | struct buffer_head *, unsigned int); | 1585 | struct buffer_head *, unsigned int); |
1586 | #define ext4_check_dir_entry(dir, de, bh, offset) \ | ||
1587 | __ext4_check_dir_entry(__func__, __LINE__, (dir), (de), (bh), (offset)) | ||
1516 | extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, | 1588 | extern int ext4_htree_store_dirent(struct file *dir_file, __u32 hash, |
1517 | __u32 minor_hash, | 1589 | __u32 minor_hash, |
1518 | struct ext4_dir_entry_2 *dirent); | 1590 | struct ext4_dir_entry_2 *dirent); |
@@ -1601,8 +1673,6 @@ extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long); | |||
1601 | extern int ext4_ext_migrate(struct inode *); | 1673 | extern int ext4_ext_migrate(struct inode *); |
1602 | 1674 | ||
1603 | /* namei.c */ | 1675 | /* namei.c */ |
1604 | extern unsigned int ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize); | ||
1605 | extern __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize); | ||
1606 | extern int ext4_orphan_add(handle_t *, struct inode *); | 1676 | extern int ext4_orphan_add(handle_t *, struct inode *); |
1607 | extern int ext4_orphan_del(handle_t *, struct inode *); | 1677 | extern int ext4_orphan_del(handle_t *, struct inode *); |
1608 | extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, | 1678 | extern int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash, |
@@ -1616,25 +1686,38 @@ extern int ext4_group_extend(struct super_block *sb, | |||
1616 | ext4_fsblk_t n_blocks_count); | 1686 | ext4_fsblk_t n_blocks_count); |
1617 | 1687 | ||
1618 | /* super.c */ | 1688 | /* super.c */ |
1619 | extern void __ext4_error(struct super_block *, const char *, const char *, ...) | 1689 | extern void __ext4_error(struct super_block *, const char *, unsigned int, |
1620 | __attribute__ ((format (printf, 3, 4))); | 1690 | const char *, ...) |
1621 | #define ext4_error(sb, message...) __ext4_error(sb, __func__, ## message) | 1691 | __attribute__ ((format (printf, 4, 5))); |
1622 | extern void ext4_error_inode(const char *, struct inode *, const char *, ...) | 1692 | #define ext4_error(sb, message...) __ext4_error(sb, __func__, \ |
1623 | __attribute__ ((format (printf, 3, 4))); | 1693 | __LINE__, ## message) |
1624 | extern void ext4_error_file(const char *, struct file *, const char *, ...) | 1694 | extern void ext4_error_inode(struct inode *, const char *, unsigned int, |
1625 | __attribute__ ((format (printf, 3, 4))); | 1695 | ext4_fsblk_t, const char *, ...) |
1626 | extern void __ext4_std_error(struct super_block *, const char *, int); | 1696 | __attribute__ ((format (printf, 5, 6))); |
1627 | extern void ext4_abort(struct super_block *, const char *, const char *, ...) | 1697 | extern void ext4_error_file(struct file *, const char *, unsigned int, |
1628 | __attribute__ ((format (printf, 3, 4))); | 1698 | const char *, ...) |
1629 | extern void __ext4_warning(struct super_block *, const char *, | 1699 | __attribute__ ((format (printf, 4, 5))); |
1700 | extern void __ext4_std_error(struct super_block *, const char *, | ||
1701 | unsigned int, int); | ||
1702 | extern void __ext4_abort(struct super_block *, const char *, unsigned int, | ||
1703 | const char *, ...) | ||
1704 | __attribute__ ((format (printf, 4, 5))); | ||
1705 | #define ext4_abort(sb, message...) __ext4_abort(sb, __func__, \ | ||
1706 | __LINE__, ## message) | ||
1707 | extern void __ext4_warning(struct super_block *, const char *, unsigned int, | ||
1630 | const char *, ...) | 1708 | const char *, ...) |
1631 | __attribute__ ((format (printf, 3, 4))); | 1709 | __attribute__ ((format (printf, 4, 5))); |
1632 | #define ext4_warning(sb, message...) __ext4_warning(sb, __func__, ## message) | 1710 | #define ext4_warning(sb, message...) __ext4_warning(sb, __func__, \ |
1711 | __LINE__, ## message) | ||
1633 | extern void ext4_msg(struct super_block *, const char *, const char *, ...) | 1712 | extern void ext4_msg(struct super_block *, const char *, const char *, ...) |
1634 | __attribute__ ((format (printf, 3, 4))); | 1713 | __attribute__ ((format (printf, 3, 4))); |
1635 | extern void ext4_grp_locked_error(struct super_block *, ext4_group_t, | 1714 | extern void __ext4_grp_locked_error(const char *, unsigned int, \ |
1636 | const char *, const char *, ...) | 1715 | struct super_block *, ext4_group_t, \ |
1637 | __attribute__ ((format (printf, 4, 5))); | 1716 | unsigned long, ext4_fsblk_t, \ |
1717 | const char *, ...) | ||
1718 | __attribute__ ((format (printf, 7, 8))); | ||
1719 | #define ext4_grp_locked_error(sb, grp, message...) \ | ||
1720 | __ext4_grp_locked_error(__func__, __LINE__, (sb), (grp), ## message) | ||
1638 | extern void ext4_update_dynamic_rev(struct super_block *sb); | 1721 | extern void ext4_update_dynamic_rev(struct super_block *sb); |
1639 | extern int ext4_update_compat_feature(handle_t *handle, struct super_block *sb, | 1722 | extern int ext4_update_compat_feature(handle_t *handle, struct super_block *sb, |
1640 | __u32 compat); | 1723 | __u32 compat); |
@@ -1768,7 +1851,7 @@ static inline unsigned int ext4_flex_bg_size(struct ext4_sb_info *sbi) | |||
1768 | #define ext4_std_error(sb, errno) \ | 1851 | #define ext4_std_error(sb, errno) \ |
1769 | do { \ | 1852 | do { \ |
1770 | if ((errno)) \ | 1853 | if ((errno)) \ |
1771 | __ext4_std_error((sb), __func__, (errno)); \ | 1854 | __ext4_std_error((sb), __func__, __LINE__, (errno)); \ |
1772 | } while (0) | 1855 | } while (0) |
1773 | 1856 | ||
1774 | #ifdef CONFIG_SMP | 1857 | #ifdef CONFIG_SMP |
@@ -1860,6 +1943,12 @@ static inline void ext4_unlock_group(struct super_block *sb, | |||
1860 | spin_unlock(ext4_group_lock_ptr(sb, group)); | 1943 | spin_unlock(ext4_group_lock_ptr(sb, group)); |
1861 | } | 1944 | } |
1862 | 1945 | ||
1946 | static inline void ext4_mark_super_dirty(struct super_block *sb) | ||
1947 | { | ||
1948 | if (EXT4_SB(sb)->s_journal == NULL) | ||
1949 | sb->s_dirt =1; | ||
1950 | } | ||
1951 | |||
1863 | /* | 1952 | /* |
1864 | * Inodes and files operations | 1953 | * Inodes and files operations |
1865 | */ | 1954 | */ |
@@ -1905,9 +1994,6 @@ extern int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset, | |||
1905 | ssize_t len); | 1994 | ssize_t len); |
1906 | extern int ext4_map_blocks(handle_t *handle, struct inode *inode, | 1995 | extern int ext4_map_blocks(handle_t *handle, struct inode *inode, |
1907 | struct ext4_map_blocks *map, int flags); | 1996 | struct ext4_map_blocks *map, int flags); |
1908 | extern int ext4_get_blocks(handle_t *handle, struct inode *inode, | ||
1909 | sector_t block, unsigned int max_blocks, | ||
1910 | struct buffer_head *bh, int flags); | ||
1911 | extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 1997 | extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
1912 | __u64 start, __u64 len); | 1998 | __u64 start, __u64 len); |
1913 | /* move_extent.c */ | 1999 | /* move_extent.c */ |
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index 53d2764d71ca..6e272ef6ba96 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c | |||
@@ -6,29 +6,29 @@ | |||
6 | 6 | ||
7 | #include <trace/events/ext4.h> | 7 | #include <trace/events/ext4.h> |
8 | 8 | ||
9 | int __ext4_journal_get_undo_access(const char *where, handle_t *handle, | 9 | int __ext4_journal_get_undo_access(const char *where, unsigned int line, |
10 | struct buffer_head *bh) | 10 | handle_t *handle, struct buffer_head *bh) |
11 | { | 11 | { |
12 | int err = 0; | 12 | int err = 0; |
13 | 13 | ||
14 | if (ext4_handle_valid(handle)) { | 14 | if (ext4_handle_valid(handle)) { |
15 | err = jbd2_journal_get_undo_access(handle, bh); | 15 | err = jbd2_journal_get_undo_access(handle, bh); |
16 | if (err) | 16 | if (err) |
17 | ext4_journal_abort_handle(where, __func__, bh, | 17 | ext4_journal_abort_handle(where, line, __func__, bh, |
18 | handle, err); | 18 | handle, err); |
19 | } | 19 | } |
20 | return err; | 20 | return err; |
21 | } | 21 | } |
22 | 22 | ||
23 | int __ext4_journal_get_write_access(const char *where, handle_t *handle, | 23 | int __ext4_journal_get_write_access(const char *where, unsigned int line, |
24 | struct buffer_head *bh) | 24 | handle_t *handle, struct buffer_head *bh) |
25 | { | 25 | { |
26 | int err = 0; | 26 | int err = 0; |
27 | 27 | ||
28 | if (ext4_handle_valid(handle)) { | 28 | if (ext4_handle_valid(handle)) { |
29 | err = jbd2_journal_get_write_access(handle, bh); | 29 | err = jbd2_journal_get_write_access(handle, bh); |
30 | if (err) | 30 | if (err) |
31 | ext4_journal_abort_handle(where, __func__, bh, | 31 | ext4_journal_abort_handle(where, line, __func__, bh, |
32 | handle, err); | 32 | handle, err); |
33 | } | 33 | } |
34 | return err; | 34 | return err; |
@@ -46,9 +46,9 @@ int __ext4_journal_get_write_access(const char *where, handle_t *handle, | |||
46 | * If the handle isn't valid we're not journaling, but we still need to | 46 | * If the handle isn't valid we're not journaling, but we still need to |
47 | * call into ext4_journal_revoke() to put the buffer head. | 47 | * call into ext4_journal_revoke() to put the buffer head. |
48 | */ | 48 | */ |
49 | int __ext4_forget(const char *where, handle_t *handle, int is_metadata, | 49 | int __ext4_forget(const char *where, unsigned int line, handle_t *handle, |
50 | struct inode *inode, struct buffer_head *bh, | 50 | int is_metadata, struct inode *inode, |
51 | ext4_fsblk_t blocknr) | 51 | struct buffer_head *bh, ext4_fsblk_t blocknr) |
52 | { | 52 | { |
53 | int err; | 53 | int err; |
54 | 54 | ||
@@ -79,8 +79,8 @@ int __ext4_forget(const char *where, handle_t *handle, int is_metadata, | |||
79 | BUFFER_TRACE(bh, "call jbd2_journal_forget"); | 79 | BUFFER_TRACE(bh, "call jbd2_journal_forget"); |
80 | err = jbd2_journal_forget(handle, bh); | 80 | err = jbd2_journal_forget(handle, bh); |
81 | if (err) | 81 | if (err) |
82 | ext4_journal_abort_handle(where, __func__, bh, | 82 | ext4_journal_abort_handle(where, line, __func__, |
83 | handle, err); | 83 | bh, handle, err); |
84 | return err; | 84 | return err; |
85 | } | 85 | } |
86 | return 0; | 86 | return 0; |
@@ -92,15 +92,16 @@ int __ext4_forget(const char *where, handle_t *handle, int is_metadata, | |||
92 | BUFFER_TRACE(bh, "call jbd2_journal_revoke"); | 92 | BUFFER_TRACE(bh, "call jbd2_journal_revoke"); |
93 | err = jbd2_journal_revoke(handle, blocknr, bh); | 93 | err = jbd2_journal_revoke(handle, blocknr, bh); |
94 | if (err) { | 94 | if (err) { |
95 | ext4_journal_abort_handle(where, __func__, bh, handle, err); | 95 | ext4_journal_abort_handle(where, line, __func__, |
96 | ext4_abort(inode->i_sb, __func__, | 96 | bh, handle, err); |
97 | __ext4_abort(inode->i_sb, where, line, | ||
97 | "error %d when attempting revoke", err); | 98 | "error %d when attempting revoke", err); |
98 | } | 99 | } |
99 | BUFFER_TRACE(bh, "exit"); | 100 | BUFFER_TRACE(bh, "exit"); |
100 | return err; | 101 | return err; |
101 | } | 102 | } |
102 | 103 | ||
103 | int __ext4_journal_get_create_access(const char *where, | 104 | int __ext4_journal_get_create_access(const char *where, unsigned int line, |
104 | handle_t *handle, struct buffer_head *bh) | 105 | handle_t *handle, struct buffer_head *bh) |
105 | { | 106 | { |
106 | int err = 0; | 107 | int err = 0; |
@@ -108,22 +109,23 @@ int __ext4_journal_get_create_access(const char *where, | |||
108 | if (ext4_handle_valid(handle)) { | 109 | if (ext4_handle_valid(handle)) { |
109 | err = jbd2_journal_get_create_access(handle, bh); | 110 | err = jbd2_journal_get_create_access(handle, bh); |
110 | if (err) | 111 | if (err) |
111 | ext4_journal_abort_handle(where, __func__, bh, | 112 | ext4_journal_abort_handle(where, line, __func__, |
112 | handle, err); | 113 | bh, handle, err); |
113 | } | 114 | } |
114 | return err; | 115 | return err; |
115 | } | 116 | } |
116 | 117 | ||
117 | int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, | 118 | int __ext4_handle_dirty_metadata(const char *where, unsigned int line, |
118 | struct inode *inode, struct buffer_head *bh) | 119 | handle_t *handle, struct inode *inode, |
120 | struct buffer_head *bh) | ||
119 | { | 121 | { |
120 | int err = 0; | 122 | int err = 0; |
121 | 123 | ||
122 | if (ext4_handle_valid(handle)) { | 124 | if (ext4_handle_valid(handle)) { |
123 | err = jbd2_journal_dirty_metadata(handle, bh); | 125 | err = jbd2_journal_dirty_metadata(handle, bh); |
124 | if (err) | 126 | if (err) |
125 | ext4_journal_abort_handle(where, __func__, bh, | 127 | ext4_journal_abort_handle(where, line, __func__, |
126 | handle, err); | 128 | bh, handle, err); |
127 | } else { | 129 | } else { |
128 | if (inode) | 130 | if (inode) |
129 | mark_buffer_dirty_inode(bh, inode); | 131 | mark_buffer_dirty_inode(bh, inode); |
@@ -132,14 +134,33 @@ int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, | |||
132 | if (inode && inode_needs_sync(inode)) { | 134 | if (inode && inode_needs_sync(inode)) { |
133 | sync_dirty_buffer(bh); | 135 | sync_dirty_buffer(bh); |
134 | if (buffer_req(bh) && !buffer_uptodate(bh)) { | 136 | if (buffer_req(bh) && !buffer_uptodate(bh)) { |
135 | ext4_error(inode->i_sb, | 137 | struct ext4_super_block *es; |
136 | "IO error syncing inode, " | 138 | |
137 | "inode=%lu, block=%llu", | 139 | es = EXT4_SB(inode->i_sb)->s_es; |
138 | inode->i_ino, | 140 | es->s_last_error_block = |
139 | (unsigned long long) bh->b_blocknr); | 141 | cpu_to_le64(bh->b_blocknr); |
142 | ext4_error_inode(inode, where, line, | ||
143 | bh->b_blocknr, | ||
144 | "IO error syncing itable block"); | ||
140 | err = -EIO; | 145 | err = -EIO; |
141 | } | 146 | } |
142 | } | 147 | } |
143 | } | 148 | } |
144 | return err; | 149 | return err; |
145 | } | 150 | } |
151 | |||
152 | int __ext4_handle_dirty_super(const char *where, unsigned int line, | ||
153 | handle_t *handle, struct super_block *sb) | ||
154 | { | ||
155 | struct buffer_head *bh = EXT4_SB(sb)->s_sbh; | ||
156 | int err = 0; | ||
157 | |||
158 | if (ext4_handle_valid(handle)) { | ||
159 | err = jbd2_journal_dirty_metadata(handle, bh); | ||
160 | if (err) | ||
161 | ext4_journal_abort_handle(where, line, __func__, | ||
162 | bh, handle, err); | ||
163 | } else | ||
164 | sb->s_dirt = 1; | ||
165 | return err; | ||
166 | } | ||
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index dade0c024797..b0bd792c58c5 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h | |||
@@ -122,39 +122,47 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode); | |||
122 | /* | 122 | /* |
123 | * Wrapper functions with which ext4 calls into JBD. | 123 | * Wrapper functions with which ext4 calls into JBD. |
124 | */ | 124 | */ |
125 | void ext4_journal_abort_handle(const char *caller, const char *err_fn, | 125 | void ext4_journal_abort_handle(const char *caller, unsigned int line, |
126 | const char *err_fn, | ||
126 | struct buffer_head *bh, handle_t *handle, int err); | 127 | struct buffer_head *bh, handle_t *handle, int err); |
127 | 128 | ||
128 | int __ext4_journal_get_undo_access(const char *where, handle_t *handle, | 129 | int __ext4_journal_get_undo_access(const char *where, unsigned int line, |
129 | struct buffer_head *bh); | 130 | handle_t *handle, struct buffer_head *bh); |
130 | 131 | ||
131 | int __ext4_journal_get_write_access(const char *where, handle_t *handle, | 132 | int __ext4_journal_get_write_access(const char *where, unsigned int line, |
132 | struct buffer_head *bh); | 133 | handle_t *handle, struct buffer_head *bh); |
133 | 134 | ||
134 | int __ext4_forget(const char *where, handle_t *handle, int is_metadata, | 135 | int __ext4_forget(const char *where, unsigned int line, handle_t *handle, |
135 | struct inode *inode, struct buffer_head *bh, | 136 | int is_metadata, struct inode *inode, |
136 | ext4_fsblk_t blocknr); | 137 | struct buffer_head *bh, ext4_fsblk_t blocknr); |
137 | 138 | ||
138 | int __ext4_journal_get_create_access(const char *where, | 139 | int __ext4_journal_get_create_access(const char *where, unsigned int line, |
139 | handle_t *handle, struct buffer_head *bh); | 140 | handle_t *handle, struct buffer_head *bh); |
140 | 141 | ||
141 | int __ext4_handle_dirty_metadata(const char *where, handle_t *handle, | 142 | int __ext4_handle_dirty_metadata(const char *where, unsigned int line, |
142 | struct inode *inode, struct buffer_head *bh); | 143 | handle_t *handle, struct inode *inode, |
144 | struct buffer_head *bh); | ||
145 | |||
146 | int __ext4_handle_dirty_super(const char *where, unsigned int line, | ||
147 | handle_t *handle, struct super_block *sb); | ||
143 | 148 | ||
144 | #define ext4_journal_get_undo_access(handle, bh) \ | 149 | #define ext4_journal_get_undo_access(handle, bh) \ |
145 | __ext4_journal_get_undo_access(__func__, (handle), (bh)) | 150 | __ext4_journal_get_undo_access(__func__, __LINE__, (handle), (bh)) |
146 | #define ext4_journal_get_write_access(handle, bh) \ | 151 | #define ext4_journal_get_write_access(handle, bh) \ |
147 | __ext4_journal_get_write_access(__func__, (handle), (bh)) | 152 | __ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh)) |
148 | #define ext4_forget(handle, is_metadata, inode, bh, block_nr) \ | 153 | #define ext4_forget(handle, is_metadata, inode, bh, block_nr) \ |
149 | __ext4_forget(__func__, (handle), (is_metadata), (inode), (bh),\ | 154 | __ext4_forget(__func__, __LINE__, (handle), (is_metadata), (inode), \ |
150 | (block_nr)) | 155 | (bh), (block_nr)) |
151 | #define ext4_journal_get_create_access(handle, bh) \ | 156 | #define ext4_journal_get_create_access(handle, bh) \ |
152 | __ext4_journal_get_create_access(__func__, (handle), (bh)) | 157 | __ext4_journal_get_create_access(__func__, __LINE__, (handle), (bh)) |
153 | #define ext4_handle_dirty_metadata(handle, inode, bh) \ | 158 | #define ext4_handle_dirty_metadata(handle, inode, bh) \ |
154 | __ext4_handle_dirty_metadata(__func__, (handle), (inode), (bh)) | 159 | __ext4_handle_dirty_metadata(__func__, __LINE__, (handle), (inode), \ |
160 | (bh)) | ||
161 | #define ext4_handle_dirty_super(handle, sb) \ | ||
162 | __ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb)) | ||
155 | 163 | ||
156 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks); | 164 | handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks); |
157 | int __ext4_journal_stop(const char *where, handle_t *handle); | 165 | int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle); |
158 | 166 | ||
159 | #define EXT4_NOJOURNAL_MAX_REF_COUNT ((unsigned long) 4096) | 167 | #define EXT4_NOJOURNAL_MAX_REF_COUNT ((unsigned long) 4096) |
160 | 168 | ||
@@ -207,7 +215,7 @@ static inline handle_t *ext4_journal_start(struct inode *inode, int nblocks) | |||
207 | } | 215 | } |
208 | 216 | ||
209 | #define ext4_journal_stop(handle) \ | 217 | #define ext4_journal_stop(handle) \ |
210 | __ext4_journal_stop(__func__, (handle)) | 218 | __ext4_journal_stop(__func__, __LINE__, (handle)) |
211 | 219 | ||
212 | static inline handle_t *ext4_journal_current_handle(void) | 220 | static inline handle_t *ext4_journal_current_handle(void) |
213 | { | 221 | { |
@@ -308,17 +316,15 @@ static inline int ext4_should_writeback_data(struct inode *inode) | |||
308 | * This function controls whether or not we should try to go down the | 316 | * This function controls whether or not we should try to go down the |
309 | * dioread_nolock code paths, which makes it safe to avoid taking | 317 | * dioread_nolock code paths, which makes it safe to avoid taking |
310 | * i_mutex for direct I/O reads. This only works for extent-based | 318 | * i_mutex for direct I/O reads. This only works for extent-based |
311 | * files, and it doesn't work for nobh or if data journaling is | 319 | * files, and it doesn't work if data journaling is enabled, since the |
312 | * enabled, since the dioread_nolock code uses b_private to pass | 320 | * dioread_nolock code uses b_private to pass information back to the |
313 | * information back to the I/O completion handler, and this conflicts | 321 | * I/O completion handler, and this conflicts with the jbd's use of |
314 | * with the jbd's use of b_private. | 322 | * b_private. |
315 | */ | 323 | */ |
316 | static inline int ext4_should_dioread_nolock(struct inode *inode) | 324 | static inline int ext4_should_dioread_nolock(struct inode *inode) |
317 | { | 325 | { |
318 | if (!test_opt(inode->i_sb, DIOREAD_NOLOCK)) | 326 | if (!test_opt(inode->i_sb, DIOREAD_NOLOCK)) |
319 | return 0; | 327 | return 0; |
320 | if (test_opt(inode->i_sb, NOBH)) | ||
321 | return 0; | ||
322 | if (!S_ISREG(inode->i_mode)) | 328 | if (!S_ISREG(inode->i_mode)) |
323 | return 0; | 329 | return 0; |
324 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) | 330 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 377309c1af65..06328d3e5717 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -401,9 +401,9 @@ static int ext4_valid_extent_entries(struct inode *inode, | |||
401 | return 1; | 401 | return 1; |
402 | } | 402 | } |
403 | 403 | ||
404 | static int __ext4_ext_check(const char *function, struct inode *inode, | 404 | static int __ext4_ext_check(const char *function, unsigned int line, |
405 | struct ext4_extent_header *eh, | 405 | struct inode *inode, struct ext4_extent_header *eh, |
406 | int depth) | 406 | int depth) |
407 | { | 407 | { |
408 | const char *error_msg; | 408 | const char *error_msg; |
409 | int max = 0; | 409 | int max = 0; |
@@ -436,7 +436,7 @@ static int __ext4_ext_check(const char *function, struct inode *inode, | |||
436 | return 0; | 436 | return 0; |
437 | 437 | ||
438 | corrupted: | 438 | corrupted: |
439 | ext4_error_inode(function, inode, | 439 | ext4_error_inode(inode, function, line, 0, |
440 | "bad header/extent: %s - magic %x, " | 440 | "bad header/extent: %s - magic %x, " |
441 | "entries %u, max %u(%u), depth %u(%u)", | 441 | "entries %u, max %u(%u), depth %u(%u)", |
442 | error_msg, le16_to_cpu(eh->eh_magic), | 442 | error_msg, le16_to_cpu(eh->eh_magic), |
@@ -447,7 +447,7 @@ corrupted: | |||
447 | } | 447 | } |
448 | 448 | ||
449 | #define ext4_ext_check(inode, eh, depth) \ | 449 | #define ext4_ext_check(inode, eh, depth) \ |
450 | __ext4_ext_check(__func__, inode, eh, depth) | 450 | __ext4_ext_check(__func__, __LINE__, inode, eh, depth) |
451 | 451 | ||
452 | int ext4_ext_check_inode(struct inode *inode) | 452 | int ext4_ext_check_inode(struct inode *inode) |
453 | { | 453 | { |
@@ -1083,7 +1083,6 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
1083 | { | 1083 | { |
1084 | struct ext4_ext_path *curp = path; | 1084 | struct ext4_ext_path *curp = path; |
1085 | struct ext4_extent_header *neh; | 1085 | struct ext4_extent_header *neh; |
1086 | struct ext4_extent_idx *fidx; | ||
1087 | struct buffer_head *bh; | 1086 | struct buffer_head *bh; |
1088 | ext4_fsblk_t newblock; | 1087 | ext4_fsblk_t newblock; |
1089 | int err = 0; | 1088 | int err = 0; |
@@ -1144,10 +1143,10 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
1144 | ext4_idx_store_pblock(curp->p_idx, newblock); | 1143 | ext4_idx_store_pblock(curp->p_idx, newblock); |
1145 | 1144 | ||
1146 | neh = ext_inode_hdr(inode); | 1145 | neh = ext_inode_hdr(inode); |
1147 | fidx = EXT_FIRST_INDEX(neh); | ||
1148 | ext_debug("new root: num %d(%d), lblock %d, ptr %llu\n", | 1146 | ext_debug("new root: num %d(%d), lblock %d, ptr %llu\n", |
1149 | le16_to_cpu(neh->eh_entries), le16_to_cpu(neh->eh_max), | 1147 | le16_to_cpu(neh->eh_entries), le16_to_cpu(neh->eh_max), |
1150 | le32_to_cpu(fidx->ei_block), idx_pblock(fidx)); | 1148 | le32_to_cpu(EXT_FIRST_INDEX(neh)->ei_block), |
1149 | idx_pblock(EXT_FIRST_INDEX(neh))); | ||
1151 | 1150 | ||
1152 | neh->eh_depth = cpu_to_le16(path->p_depth + 1); | 1151 | neh->eh_depth = cpu_to_le16(path->p_depth + 1); |
1153 | err = ext4_ext_dirty(handle, inode, curp); | 1152 | err = ext4_ext_dirty(handle, inode, curp); |
@@ -2937,7 +2936,7 @@ fix_extent_len: | |||
2937 | * One of more index blocks maybe needed if the extent tree grow after | 2936 | * One of more index blocks maybe needed if the extent tree grow after |
2938 | * the unintialized extent split. To prevent ENOSPC occur at the IO | 2937 | * the unintialized extent split. To prevent ENOSPC occur at the IO |
2939 | * complete, we need to split the uninitialized extent before DIO submit | 2938 | * complete, we need to split the uninitialized extent before DIO submit |
2940 | * the IO. The uninitilized extent called at this time will be split | 2939 | * the IO. The uninitialized extent called at this time will be split |
2941 | * into three uninitialized extent(at most). After IO complete, the part | 2940 | * into three uninitialized extent(at most). After IO complete, the part |
2942 | * being filled will be convert to initialized by the end_io callback function | 2941 | * being filled will be convert to initialized by the end_io callback function |
2943 | * via ext4_convert_unwritten_extents(). | 2942 | * via ext4_convert_unwritten_extents(). |
@@ -2954,7 +2953,6 @@ static int ext4_split_unwritten_extents(handle_t *handle, | |||
2954 | struct ext4_extent *ex1 = NULL; | 2953 | struct ext4_extent *ex1 = NULL; |
2955 | struct ext4_extent *ex2 = NULL; | 2954 | struct ext4_extent *ex2 = NULL; |
2956 | struct ext4_extent *ex3 = NULL; | 2955 | struct ext4_extent *ex3 = NULL; |
2957 | struct ext4_extent_header *eh; | ||
2958 | ext4_lblk_t ee_block, eof_block; | 2956 | ext4_lblk_t ee_block, eof_block; |
2959 | unsigned int allocated, ee_len, depth; | 2957 | unsigned int allocated, ee_len, depth; |
2960 | ext4_fsblk_t newblock; | 2958 | ext4_fsblk_t newblock; |
@@ -2971,7 +2969,6 @@ static int ext4_split_unwritten_extents(handle_t *handle, | |||
2971 | eof_block = map->m_lblk + map->m_len; | 2969 | eof_block = map->m_lblk + map->m_len; |
2972 | 2970 | ||
2973 | depth = ext_depth(inode); | 2971 | depth = ext_depth(inode); |
2974 | eh = path[depth].p_hdr; | ||
2975 | ex = path[depth].p_ext; | 2972 | ex = path[depth].p_ext; |
2976 | ee_block = le32_to_cpu(ex->ee_block); | 2973 | ee_block = le32_to_cpu(ex->ee_block); |
2977 | ee_len = ext4_ext_get_actual_len(ex); | 2974 | ee_len = ext4_ext_get_actual_len(ex); |
@@ -3058,7 +3055,6 @@ static int ext4_split_unwritten_extents(handle_t *handle, | |||
3058 | err = PTR_ERR(path); | 3055 | err = PTR_ERR(path); |
3059 | goto out; | 3056 | goto out; |
3060 | } | 3057 | } |
3061 | eh = path[depth].p_hdr; | ||
3062 | ex = path[depth].p_ext; | 3058 | ex = path[depth].p_ext; |
3063 | if (ex2 != &newex) | 3059 | if (ex2 != &newex) |
3064 | ex2 = ex; | 3060 | ex2 = ex; |
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 5313ae4cda2d..ee92b66d4558 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c | |||
@@ -70,7 +70,8 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
70 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 70 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
71 | size_t length = iov_length(iov, nr_segs); | 71 | size_t length = iov_length(iov, nr_segs); |
72 | 72 | ||
73 | if (pos > sbi->s_bitmap_maxbytes) | 73 | if ((pos > sbi->s_bitmap_maxbytes || |
74 | (pos == sbi->s_bitmap_maxbytes && length > 0))) | ||
74 | return -EFBIG; | 75 | return -EFBIG; |
75 | 76 | ||
76 | if (pos + length > sbi->s_bitmap_maxbytes) { | 77 | if (pos + length > sbi->s_bitmap_maxbytes) { |
@@ -123,7 +124,7 @@ static int ext4_file_open(struct inode * inode, struct file * filp) | |||
123 | if (!IS_ERR(cp)) { | 124 | if (!IS_ERR(cp)) { |
124 | memcpy(sbi->s_es->s_last_mounted, cp, | 125 | memcpy(sbi->s_es->s_last_mounted, cp, |
125 | sizeof(sbi->s_es->s_last_mounted)); | 126 | sizeof(sbi->s_es->s_last_mounted)); |
126 | sb->s_dirt = 1; | 127 | ext4_mark_super_dirty(sb); |
127 | } | 128 | } |
128 | } | 129 | } |
129 | return dquot_file_open(inode, filp); | 130 | return dquot_file_open(inode, filp); |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 25c4b3173fd9..ac377505ed57 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -279,7 +279,7 @@ out: | |||
279 | err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); | 279 | err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); |
280 | if (!fatal) | 280 | if (!fatal) |
281 | fatal = err; | 281 | fatal = err; |
282 | sb->s_dirt = 1; | 282 | ext4_mark_super_dirty(sb); |
283 | } else | 283 | } else |
284 | ext4_error(sb, "bit already cleared for inode %lu", ino); | 284 | ext4_error(sb, "bit already cleared for inode %lu", ino); |
285 | 285 | ||
@@ -965,7 +965,7 @@ got: | |||
965 | percpu_counter_dec(&sbi->s_freeinodes_counter); | 965 | percpu_counter_dec(&sbi->s_freeinodes_counter); |
966 | if (S_ISDIR(mode)) | 966 | if (S_ISDIR(mode)) |
967 | percpu_counter_inc(&sbi->s_dirs_counter); | 967 | percpu_counter_inc(&sbi->s_dirs_counter); |
968 | sb->s_dirt = 1; | 968 | ext4_mark_super_dirty(sb); |
969 | 969 | ||
970 | if (sbi->s_log_groups_per_flex) { | 970 | if (sbi->s_log_groups_per_flex) { |
971 | flex_group = ext4_flex_group(sbi, group); | 971 | flex_group = ext4_flex_group(sbi, group); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 42272d67955a..a0ab3754d0d6 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -221,6 +221,7 @@ void ext4_delete_inode(struct inode *inode) | |||
221 | "couldn't extend journal (err %d)", err); | 221 | "couldn't extend journal (err %d)", err); |
222 | stop_handle: | 222 | stop_handle: |
223 | ext4_journal_stop(handle); | 223 | ext4_journal_stop(handle); |
224 | ext4_orphan_del(NULL, inode); | ||
224 | goto no_delete; | 225 | goto no_delete; |
225 | } | 226 | } |
226 | } | 227 | } |
@@ -337,9 +338,11 @@ static int ext4_block_to_path(struct inode *inode, | |||
337 | return n; | 338 | return n; |
338 | } | 339 | } |
339 | 340 | ||
340 | static int __ext4_check_blockref(const char *function, struct inode *inode, | 341 | static int __ext4_check_blockref(const char *function, unsigned int line, |
342 | struct inode *inode, | ||
341 | __le32 *p, unsigned int max) | 343 | __le32 *p, unsigned int max) |
342 | { | 344 | { |
345 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; | ||
343 | __le32 *bref = p; | 346 | __le32 *bref = p; |
344 | unsigned int blk; | 347 | unsigned int blk; |
345 | 348 | ||
@@ -348,8 +351,9 @@ static int __ext4_check_blockref(const char *function, struct inode *inode, | |||
348 | if (blk && | 351 | if (blk && |
349 | unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb), | 352 | unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb), |
350 | blk, 1))) { | 353 | blk, 1))) { |
351 | ext4_error_inode(function, inode, | 354 | es->s_last_error_block = cpu_to_le64(blk); |
352 | "invalid block reference %u", blk); | 355 | ext4_error_inode(inode, function, line, blk, |
356 | "invalid block"); | ||
353 | return -EIO; | 357 | return -EIO; |
354 | } | 358 | } |
355 | } | 359 | } |
@@ -358,11 +362,13 @@ static int __ext4_check_blockref(const char *function, struct inode *inode, | |||
358 | 362 | ||
359 | 363 | ||
360 | #define ext4_check_indirect_blockref(inode, bh) \ | 364 | #define ext4_check_indirect_blockref(inode, bh) \ |
361 | __ext4_check_blockref(__func__, inode, (__le32 *)(bh)->b_data, \ | 365 | __ext4_check_blockref(__func__, __LINE__, inode, \ |
366 | (__le32 *)(bh)->b_data, \ | ||
362 | EXT4_ADDR_PER_BLOCK((inode)->i_sb)) | 367 | EXT4_ADDR_PER_BLOCK((inode)->i_sb)) |
363 | 368 | ||
364 | #define ext4_check_inode_blockref(inode) \ | 369 | #define ext4_check_inode_blockref(inode) \ |
365 | __ext4_check_blockref(__func__, inode, EXT4_I(inode)->i_data, \ | 370 | __ext4_check_blockref(__func__, __LINE__, inode, \ |
371 | EXT4_I(inode)->i_data, \ | ||
366 | EXT4_NDIR_BLOCKS) | 372 | EXT4_NDIR_BLOCKS) |
367 | 373 | ||
368 | /** | 374 | /** |
@@ -1128,20 +1134,24 @@ void ext4_da_update_reserve_space(struct inode *inode, | |||
1128 | ext4_discard_preallocations(inode); | 1134 | ext4_discard_preallocations(inode); |
1129 | } | 1135 | } |
1130 | 1136 | ||
1131 | static int check_block_validity(struct inode *inode, const char *func, | 1137 | static int __check_block_validity(struct inode *inode, const char *func, |
1138 | unsigned int line, | ||
1132 | struct ext4_map_blocks *map) | 1139 | struct ext4_map_blocks *map) |
1133 | { | 1140 | { |
1134 | if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk, | 1141 | if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk, |
1135 | map->m_len)) { | 1142 | map->m_len)) { |
1136 | ext4_error_inode(func, inode, | 1143 | ext4_error_inode(inode, func, line, map->m_pblk, |
1137 | "lblock %lu mapped to illegal pblock %llu " | 1144 | "lblock %lu mapped to illegal pblock " |
1138 | "(length %d)", (unsigned long) map->m_lblk, | 1145 | "(length %d)", (unsigned long) map->m_lblk, |
1139 | map->m_pblk, map->m_len); | 1146 | map->m_len); |
1140 | return -EIO; | 1147 | return -EIO; |
1141 | } | 1148 | } |
1142 | return 0; | 1149 | return 0; |
1143 | } | 1150 | } |
1144 | 1151 | ||
1152 | #define check_block_validity(inode, map) \ | ||
1153 | __check_block_validity((inode), __func__, __LINE__, (map)) | ||
1154 | |||
1145 | /* | 1155 | /* |
1146 | * Return the number of contiguous dirty pages in a given inode | 1156 | * Return the number of contiguous dirty pages in a given inode |
1147 | * starting at page frame idx. | 1157 | * starting at page frame idx. |
@@ -1244,7 +1254,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
1244 | up_read((&EXT4_I(inode)->i_data_sem)); | 1254 | up_read((&EXT4_I(inode)->i_data_sem)); |
1245 | 1255 | ||
1246 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { | 1256 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { |
1247 | int ret = check_block_validity(inode, __func__, map); | 1257 | int ret = check_block_validity(inode, map); |
1248 | if (ret != 0) | 1258 | if (ret != 0) |
1249 | return ret; | 1259 | return ret; |
1250 | } | 1260 | } |
@@ -1324,9 +1334,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, | |||
1324 | 1334 | ||
1325 | up_write((&EXT4_I(inode)->i_data_sem)); | 1335 | up_write((&EXT4_I(inode)->i_data_sem)); |
1326 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { | 1336 | if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { |
1327 | int ret = check_block_validity(inode, | 1337 | int ret = check_block_validity(inode, map); |
1328 | "ext4_map_blocks_after_alloc", | ||
1329 | map); | ||
1330 | if (ret != 0) | 1338 | if (ret != 0) |
1331 | return ret; | 1339 | return ret; |
1332 | } | 1340 | } |
@@ -1519,9 +1527,25 @@ static int walk_page_buffers(handle_t *handle, | |||
1519 | static int do_journal_get_write_access(handle_t *handle, | 1527 | static int do_journal_get_write_access(handle_t *handle, |
1520 | struct buffer_head *bh) | 1528 | struct buffer_head *bh) |
1521 | { | 1529 | { |
1530 | int dirty = buffer_dirty(bh); | ||
1531 | int ret; | ||
1532 | |||
1522 | if (!buffer_mapped(bh) || buffer_freed(bh)) | 1533 | if (!buffer_mapped(bh) || buffer_freed(bh)) |
1523 | return 0; | 1534 | return 0; |
1524 | return ext4_journal_get_write_access(handle, bh); | 1535 | /* |
1536 | * __block_prepare_write() could have dirtied some buffers. Clean | ||
1537 | * the dirty bit as jbd2_journal_get_write_access() could complain | ||
1538 | * otherwise about fs integrity issues. Setting of the dirty bit | ||
1539 | * by __block_prepare_write() isn't a real problem here as we clear | ||
1540 | * the bit before releasing a page lock and thus writeback cannot | ||
1541 | * ever write the buffer. | ||
1542 | */ | ||
1543 | if (dirty) | ||
1544 | clear_buffer_dirty(bh); | ||
1545 | ret = ext4_journal_get_write_access(handle, bh); | ||
1546 | if (!ret && dirty) | ||
1547 | ret = ext4_handle_dirty_metadata(handle, NULL, bh); | ||
1548 | return ret; | ||
1525 | } | 1549 | } |
1526 | 1550 | ||
1527 | /* | 1551 | /* |
@@ -2194,7 +2218,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
2194 | BUG_ON(!handle); | 2218 | BUG_ON(!handle); |
2195 | 2219 | ||
2196 | /* | 2220 | /* |
2197 | * Call ext4_get_blocks() to allocate any delayed allocation | 2221 | * Call ext4_map_blocks() to allocate any delayed allocation |
2198 | * blocks, or to convert an uninitialized extent to be | 2222 | * blocks, or to convert an uninitialized extent to be |
2199 | * initialized (in the case where we have written into | 2223 | * initialized (in the case where we have written into |
2200 | * one or more preallocated blocks). | 2224 | * one or more preallocated blocks). |
@@ -2203,7 +2227,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
2203 | * indicate that we are on the delayed allocation path. This | 2227 | * indicate that we are on the delayed allocation path. This |
2204 | * affects functions in many different parts of the allocation | 2228 | * affects functions in many different parts of the allocation |
2205 | * call path. This flag exists primarily because we don't | 2229 | * call path. This flag exists primarily because we don't |
2206 | * want to change *many* call functions, so ext4_get_blocks() | 2230 | * want to change *many* call functions, so ext4_map_blocks() |
2207 | * will set the magic i_delalloc_reserved_flag once the | 2231 | * will set the magic i_delalloc_reserved_flag once the |
2208 | * inode's allocation semaphore is taken. | 2232 | * inode's allocation semaphore is taken. |
2209 | * | 2233 | * |
@@ -2221,6 +2245,8 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
2221 | 2245 | ||
2222 | blks = ext4_map_blocks(handle, mpd->inode, &map, get_blocks_flags); | 2246 | blks = ext4_map_blocks(handle, mpd->inode, &map, get_blocks_flags); |
2223 | if (blks < 0) { | 2247 | if (blks < 0) { |
2248 | struct super_block *sb = mpd->inode->i_sb; | ||
2249 | |||
2224 | err = blks; | 2250 | err = blks; |
2225 | /* | 2251 | /* |
2226 | * If get block returns with error we simply | 2252 | * If get block returns with error we simply |
@@ -2231,7 +2257,7 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
2231 | return 0; | 2257 | return 0; |
2232 | 2258 | ||
2233 | if (err == -ENOSPC && | 2259 | if (err == -ENOSPC && |
2234 | ext4_count_free_blocks(mpd->inode->i_sb)) { | 2260 | ext4_count_free_blocks(sb)) { |
2235 | mpd->retval = err; | 2261 | mpd->retval = err; |
2236 | return 0; | 2262 | return 0; |
2237 | } | 2263 | } |
@@ -2243,16 +2269,17 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
2243 | * writepage and writepages will again try to write | 2269 | * writepage and writepages will again try to write |
2244 | * the same. | 2270 | * the same. |
2245 | */ | 2271 | */ |
2246 | ext4_msg(mpd->inode->i_sb, KERN_CRIT, | 2272 | if (!(EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED)) { |
2247 | "delayed block allocation failed for inode %lu at " | 2273 | ext4_msg(sb, KERN_CRIT, |
2248 | "logical offset %llu with max blocks %zd with " | 2274 | "delayed block allocation failed for inode %lu " |
2249 | "error %d", mpd->inode->i_ino, | 2275 | "at logical offset %llu with max blocks %zd " |
2250 | (unsigned long long) next, | 2276 | "with error %d", mpd->inode->i_ino, |
2251 | mpd->b_size >> mpd->inode->i_blkbits, err); | 2277 | (unsigned long long) next, |
2252 | printk(KERN_CRIT "This should not happen!! " | 2278 | mpd->b_size >> mpd->inode->i_blkbits, err); |
2253 | "Data will be lost\n"); | 2279 | ext4_msg(sb, KERN_CRIT, |
2254 | if (err == -ENOSPC) { | 2280 | "This should not happen!! Data will be lost\n"); |
2255 | ext4_print_free_blocks(mpd->inode); | 2281 | if (err == -ENOSPC) |
2282 | ext4_print_free_blocks(mpd->inode); | ||
2256 | } | 2283 | } |
2257 | /* invalidate all the pages */ | 2284 | /* invalidate all the pages */ |
2258 | ext4_da_block_invalidatepages(mpd, next, | 2285 | ext4_da_block_invalidatepages(mpd, next, |
@@ -2320,7 +2347,7 @@ static void mpage_add_bh_to_extent(struct mpage_da_data *mpd, | |||
2320 | * XXX Don't go larger than mballoc is willing to allocate | 2347 | * XXX Don't go larger than mballoc is willing to allocate |
2321 | * This is a stopgap solution. We eventually need to fold | 2348 | * This is a stopgap solution. We eventually need to fold |
2322 | * mpage_da_submit_io() into this function and then call | 2349 | * mpage_da_submit_io() into this function and then call |
2323 | * ext4_get_blocks() multiple times in a loop | 2350 | * ext4_map_blocks() multiple times in a loop |
2324 | */ | 2351 | */ |
2325 | if (nrblocks >= 8*1024*1024/mpd->inode->i_sb->s_blocksize) | 2352 | if (nrblocks >= 8*1024*1024/mpd->inode->i_sb->s_blocksize) |
2326 | goto flush_it; | 2353 | goto flush_it; |
@@ -2553,18 +2580,16 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
2553 | /* | 2580 | /* |
2554 | * This function is used as a standard get_block_t calback function | 2581 | * This function is used as a standard get_block_t calback function |
2555 | * when there is no desire to allocate any blocks. It is used as a | 2582 | * when there is no desire to allocate any blocks. It is used as a |
2556 | * callback function for block_prepare_write(), nobh_writepage(), and | 2583 | * callback function for block_prepare_write() and block_write_full_page(). |
2557 | * block_write_full_page(). These functions should only try to map a | 2584 | * These functions should only try to map a single block at a time. |
2558 | * single block at a time. | ||
2559 | * | 2585 | * |
2560 | * Since this function doesn't do block allocations even if the caller | 2586 | * Since this function doesn't do block allocations even if the caller |
2561 | * requests it by passing in create=1, it is critically important that | 2587 | * requests it by passing in create=1, it is critically important that |
2562 | * any caller checks to make sure that any buffer heads are returned | 2588 | * any caller checks to make sure that any buffer heads are returned |
2563 | * by this function are either all already mapped or marked for | 2589 | * by this function are either all already mapped or marked for |
2564 | * delayed allocation before calling nobh_writepage() or | 2590 | * delayed allocation before calling block_write_full_page(). Otherwise, |
2565 | * block_write_full_page(). Otherwise, b_blocknr could be left | 2591 | * b_blocknr could be left unitialized, and the page write functions will |
2566 | * unitialized, and the page write functions will be taken by | 2592 | * be taken by surprise. |
2567 | * surprise. | ||
2568 | */ | 2593 | */ |
2569 | static int noalloc_get_block_write(struct inode *inode, sector_t iblock, | 2594 | static int noalloc_get_block_write(struct inode *inode, sector_t iblock, |
2570 | struct buffer_head *bh_result, int create) | 2595 | struct buffer_head *bh_result, int create) |
@@ -2749,9 +2774,7 @@ static int ext4_writepage(struct page *page, | |||
2749 | return __ext4_journalled_writepage(page, len); | 2774 | return __ext4_journalled_writepage(page, len); |
2750 | } | 2775 | } |
2751 | 2776 | ||
2752 | if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) | 2777 | if (page_bufs && buffer_uninit(page_bufs)) { |
2753 | ret = nobh_writepage(page, noalloc_get_block_write, wbc); | ||
2754 | else if (page_bufs && buffer_uninit(page_bufs)) { | ||
2755 | ext4_set_bh_endio(page_bufs, inode); | 2778 | ext4_set_bh_endio(page_bufs, inode); |
2756 | ret = block_write_full_page_endio(page, noalloc_get_block_write, | 2779 | ret = block_write_full_page_endio(page, noalloc_get_block_write, |
2757 | wbc, ext4_end_io_buffer_write); | 2780 | wbc, ext4_end_io_buffer_write); |
@@ -3146,13 +3169,10 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, | |||
3146 | int ret, retries = 0; | 3169 | int ret, retries = 0; |
3147 | struct page *page; | 3170 | struct page *page; |
3148 | pgoff_t index; | 3171 | pgoff_t index; |
3149 | unsigned from, to; | ||
3150 | struct inode *inode = mapping->host; | 3172 | struct inode *inode = mapping->host; |
3151 | handle_t *handle; | 3173 | handle_t *handle; |
3152 | 3174 | ||
3153 | index = pos >> PAGE_CACHE_SHIFT; | 3175 | index = pos >> PAGE_CACHE_SHIFT; |
3154 | from = pos & (PAGE_CACHE_SIZE - 1); | ||
3155 | to = from + len; | ||
3156 | 3176 | ||
3157 | if (ext4_nonda_switch(inode->i_sb)) { | 3177 | if (ext4_nonda_switch(inode->i_sb)) { |
3158 | *fsdata = (void *)FALL_BACK_TO_NONDELALLOC; | 3178 | *fsdata = (void *)FALL_BACK_TO_NONDELALLOC; |
@@ -3668,6 +3688,8 @@ static int ext4_end_io_nolock(ext4_io_end_t *io) | |||
3668 | return ret; | 3688 | return ret; |
3669 | } | 3689 | } |
3670 | 3690 | ||
3691 | if (io->iocb) | ||
3692 | aio_complete(io->iocb, io->result, 0); | ||
3671 | /* clear the DIO AIO unwritten flag */ | 3693 | /* clear the DIO AIO unwritten flag */ |
3672 | io->flag = 0; | 3694 | io->flag = 0; |
3673 | return ret; | 3695 | return ret; |
@@ -3767,6 +3789,8 @@ static ext4_io_end_t *ext4_init_io_end (struct inode *inode, gfp_t flags) | |||
3767 | io->offset = 0; | 3789 | io->offset = 0; |
3768 | io->size = 0; | 3790 | io->size = 0; |
3769 | io->page = NULL; | 3791 | io->page = NULL; |
3792 | io->iocb = NULL; | ||
3793 | io->result = 0; | ||
3770 | INIT_WORK(&io->work, ext4_end_io_work); | 3794 | INIT_WORK(&io->work, ext4_end_io_work); |
3771 | INIT_LIST_HEAD(&io->list); | 3795 | INIT_LIST_HEAD(&io->list); |
3772 | } | 3796 | } |
@@ -3775,7 +3799,8 @@ static ext4_io_end_t *ext4_init_io_end (struct inode *inode, gfp_t flags) | |||
3775 | } | 3799 | } |
3776 | 3800 | ||
3777 | static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, | 3801 | static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, |
3778 | ssize_t size, void *private) | 3802 | ssize_t size, void *private, int ret, |
3803 | bool is_async) | ||
3779 | { | 3804 | { |
3780 | ext4_io_end_t *io_end = iocb->private; | 3805 | ext4_io_end_t *io_end = iocb->private; |
3781 | struct workqueue_struct *wq; | 3806 | struct workqueue_struct *wq; |
@@ -3784,7 +3809,7 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, | |||
3784 | 3809 | ||
3785 | /* if not async direct IO or dio with 0 bytes write, just return */ | 3810 | /* if not async direct IO or dio with 0 bytes write, just return */ |
3786 | if (!io_end || !size) | 3811 | if (!io_end || !size) |
3787 | return; | 3812 | goto out; |
3788 | 3813 | ||
3789 | ext_debug("ext4_end_io_dio(): io_end 0x%p" | 3814 | ext_debug("ext4_end_io_dio(): io_end 0x%p" |
3790 | "for inode %lu, iocb 0x%p, offset %llu, size %llu\n", | 3815 | "for inode %lu, iocb 0x%p, offset %llu, size %llu\n", |
@@ -3795,12 +3820,18 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, | |||
3795 | if (io_end->flag != EXT4_IO_UNWRITTEN){ | 3820 | if (io_end->flag != EXT4_IO_UNWRITTEN){ |
3796 | ext4_free_io_end(io_end); | 3821 | ext4_free_io_end(io_end); |
3797 | iocb->private = NULL; | 3822 | iocb->private = NULL; |
3823 | out: | ||
3824 | if (is_async) | ||
3825 | aio_complete(iocb, ret, 0); | ||
3798 | return; | 3826 | return; |
3799 | } | 3827 | } |
3800 | 3828 | ||
3801 | io_end->offset = offset; | 3829 | io_end->offset = offset; |
3802 | io_end->size = size; | 3830 | io_end->size = size; |
3803 | io_end->flag = EXT4_IO_UNWRITTEN; | 3831 | if (is_async) { |
3832 | io_end->iocb = iocb; | ||
3833 | io_end->result = ret; | ||
3834 | } | ||
3804 | wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; | 3835 | wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; |
3805 | 3836 | ||
3806 | /* queue the work to convert unwritten extents to written */ | 3837 | /* queue the work to convert unwritten extents to written */ |
@@ -3937,7 +3968,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, | |||
3937 | return -ENOMEM; | 3968 | return -ENOMEM; |
3938 | /* | 3969 | /* |
3939 | * we save the io structure for current async | 3970 | * we save the io structure for current async |
3940 | * direct IO, so that later ext4_get_blocks() | 3971 | * direct IO, so that later ext4_map_blocks() |
3941 | * could flag the io structure whether there | 3972 | * could flag the io structure whether there |
3942 | * is a unwritten extents needs to be converted | 3973 | * is a unwritten extents needs to be converted |
3943 | * when IO is completed. | 3974 | * when IO is completed. |
@@ -4128,17 +4159,6 @@ int ext4_block_truncate_page(handle_t *handle, | |||
4128 | length = blocksize - (offset & (blocksize - 1)); | 4159 | length = blocksize - (offset & (blocksize - 1)); |
4129 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); | 4160 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); |
4130 | 4161 | ||
4131 | /* | ||
4132 | * For "nobh" option, we can only work if we don't need to | ||
4133 | * read-in the page - otherwise we create buffers to do the IO. | ||
4134 | */ | ||
4135 | if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) && | ||
4136 | ext4_should_writeback_data(inode) && PageUptodate(page)) { | ||
4137 | zero_user(page, offset, length); | ||
4138 | set_page_dirty(page); | ||
4139 | goto unlock; | ||
4140 | } | ||
4141 | |||
4142 | if (!page_has_buffers(page)) | 4162 | if (!page_has_buffers(page)) |
4143 | create_empty_buffers(page, blocksize, 0); | 4163 | create_empty_buffers(page, blocksize, 0); |
4144 | 4164 | ||
@@ -4488,9 +4508,8 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, | |||
4488 | * (should be rare). | 4508 | * (should be rare). |
4489 | */ | 4509 | */ |
4490 | if (!bh) { | 4510 | if (!bh) { |
4491 | EXT4_ERROR_INODE(inode, | 4511 | EXT4_ERROR_INODE_BLOCK(inode, nr, |
4492 | "Read failure block=%llu", | 4512 | "Read failure"); |
4493 | (unsigned long long) nr); | ||
4494 | continue; | 4513 | continue; |
4495 | } | 4514 | } |
4496 | 4515 | ||
@@ -4502,27 +4521,6 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, | |||
4502 | depth); | 4521 | depth); |
4503 | 4522 | ||
4504 | /* | 4523 | /* |
4505 | * We've probably journalled the indirect block several | ||
4506 | * times during the truncate. But it's no longer | ||
4507 | * needed and we now drop it from the transaction via | ||
4508 | * jbd2_journal_revoke(). | ||
4509 | * | ||
4510 | * That's easy if it's exclusively part of this | ||
4511 | * transaction. But if it's part of the committing | ||
4512 | * transaction then jbd2_journal_forget() will simply | ||
4513 | * brelse() it. That means that if the underlying | ||
4514 | * block is reallocated in ext4_get_block(), | ||
4515 | * unmap_underlying_metadata() will find this block | ||
4516 | * and will try to get rid of it. damn, damn. | ||
4517 | * | ||
4518 | * If this block has already been committed to the | ||
4519 | * journal, a revoke record will be written. And | ||
4520 | * revoke records must be emitted *before* clearing | ||
4521 | * this block's bit in the bitmaps. | ||
4522 | */ | ||
4523 | ext4_forget(handle, 1, inode, bh, bh->b_blocknr); | ||
4524 | |||
4525 | /* | ||
4526 | * Everything below this this pointer has been | 4524 | * Everything below this this pointer has been |
4527 | * released. Now let this top-of-subtree go. | 4525 | * released. Now let this top-of-subtree go. |
4528 | * | 4526 | * |
@@ -4546,8 +4544,20 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, | |||
4546 | blocks_for_truncate(inode)); | 4544 | blocks_for_truncate(inode)); |
4547 | } | 4545 | } |
4548 | 4546 | ||
4547 | /* | ||
4548 | * The forget flag here is critical because if | ||
4549 | * we are journaling (and not doing data | ||
4550 | * journaling), we have to make sure a revoke | ||
4551 | * record is written to prevent the journal | ||
4552 | * replay from overwriting the (former) | ||
4553 | * indirect block if it gets reallocated as a | ||
4554 | * data block. This must happen in the same | ||
4555 | * transaction where the data blocks are | ||
4556 | * actually freed. | ||
4557 | */ | ||
4549 | ext4_free_blocks(handle, inode, 0, nr, 1, | 4558 | ext4_free_blocks(handle, inode, 0, nr, 1, |
4550 | EXT4_FREE_BLOCKS_METADATA); | 4559 | EXT4_FREE_BLOCKS_METADATA| |
4560 | EXT4_FREE_BLOCKS_FORGET); | ||
4551 | 4561 | ||
4552 | if (parent_bh) { | 4562 | if (parent_bh) { |
4553 | /* | 4563 | /* |
@@ -4805,8 +4815,8 @@ static int __ext4_get_inode_loc(struct inode *inode, | |||
4805 | 4815 | ||
4806 | bh = sb_getblk(sb, block); | 4816 | bh = sb_getblk(sb, block); |
4807 | if (!bh) { | 4817 | if (!bh) { |
4808 | EXT4_ERROR_INODE(inode, "unable to read inode block - " | 4818 | EXT4_ERROR_INODE_BLOCK(inode, block, |
4809 | "block %llu", block); | 4819 | "unable to read itable block"); |
4810 | return -EIO; | 4820 | return -EIO; |
4811 | } | 4821 | } |
4812 | if (!buffer_uptodate(bh)) { | 4822 | if (!buffer_uptodate(bh)) { |
@@ -4904,8 +4914,8 @@ make_io: | |||
4904 | submit_bh(READ_META, bh); | 4914 | submit_bh(READ_META, bh); |
4905 | wait_on_buffer(bh); | 4915 | wait_on_buffer(bh); |
4906 | if (!buffer_uptodate(bh)) { | 4916 | if (!buffer_uptodate(bh)) { |
4907 | EXT4_ERROR_INODE(inode, "unable to read inode " | 4917 | EXT4_ERROR_INODE_BLOCK(inode, block, |
4908 | "block %llu", block); | 4918 | "unable to read itable block"); |
4909 | brelse(bh); | 4919 | brelse(bh); |
4910 | return -EIO; | 4920 | return -EIO; |
4911 | } | 4921 | } |
@@ -4976,7 +4986,7 @@ static blkcnt_t ext4_inode_blocks(struct ext4_inode *raw_inode, | |||
4976 | /* we are using combined 48 bit field */ | 4986 | /* we are using combined 48 bit field */ |
4977 | i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 | | 4987 | i_blocks = ((u64)le16_to_cpu(raw_inode->i_blocks_high)) << 32 | |
4978 | le32_to_cpu(raw_inode->i_blocks_lo); | 4988 | le32_to_cpu(raw_inode->i_blocks_lo); |
4979 | if (ei->i_flags & EXT4_HUGE_FILE_FL) { | 4989 | if (ext4_test_inode_flag(inode, EXT4_INODE_HUGE_FILE)) { |
4980 | /* i_blocks represent file system block size */ | 4990 | /* i_blocks represent file system block size */ |
4981 | return i_blocks << (inode->i_blkbits - 9); | 4991 | return i_blocks << (inode->i_blkbits - 9); |
4982 | } else { | 4992 | } else { |
@@ -5072,7 +5082,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
5072 | transaction_t *transaction; | 5082 | transaction_t *transaction; |
5073 | tid_t tid; | 5083 | tid_t tid; |
5074 | 5084 | ||
5075 | spin_lock(&journal->j_state_lock); | 5085 | read_lock(&journal->j_state_lock); |
5076 | if (journal->j_running_transaction) | 5086 | if (journal->j_running_transaction) |
5077 | transaction = journal->j_running_transaction; | 5087 | transaction = journal->j_running_transaction; |
5078 | else | 5088 | else |
@@ -5081,7 +5091,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
5081 | tid = transaction->t_tid; | 5091 | tid = transaction->t_tid; |
5082 | else | 5092 | else |
5083 | tid = journal->j_commit_sequence; | 5093 | tid = journal->j_commit_sequence; |
5084 | spin_unlock(&journal->j_state_lock); | 5094 | read_unlock(&journal->j_state_lock); |
5085 | ei->i_sync_tid = tid; | 5095 | ei->i_sync_tid = tid; |
5086 | ei->i_datasync_tid = tid; | 5096 | ei->i_datasync_tid = tid; |
5087 | } | 5097 | } |
@@ -5126,7 +5136,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) | |||
5126 | ei->i_file_acl); | 5136 | ei->i_file_acl); |
5127 | ret = -EIO; | 5137 | ret = -EIO; |
5128 | goto bad_inode; | 5138 | goto bad_inode; |
5129 | } else if (ei->i_flags & EXT4_EXTENTS_FL) { | 5139 | } else if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { |
5130 | if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 5140 | if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
5131 | (S_ISLNK(inode->i_mode) && | 5141 | (S_ISLNK(inode->i_mode) && |
5132 | !ext4_inode_is_fast_symlink(inode))) | 5142 | !ext4_inode_is_fast_symlink(inode))) |
@@ -5406,9 +5416,8 @@ int ext4_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
5406 | if (wbc->sync_mode == WB_SYNC_ALL) | 5416 | if (wbc->sync_mode == WB_SYNC_ALL) |
5407 | sync_dirty_buffer(iloc.bh); | 5417 | sync_dirty_buffer(iloc.bh); |
5408 | if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) { | 5418 | if (buffer_req(iloc.bh) && !buffer_uptodate(iloc.bh)) { |
5409 | EXT4_ERROR_INODE(inode, | 5419 | EXT4_ERROR_INODE_BLOCK(inode, iloc.bh->b_blocknr, |
5410 | "IO error syncing inode (block=%llu)", | 5420 | "IO error syncing inode"); |
5411 | (unsigned long long) iloc.bh->b_blocknr); | ||
5412 | err = -EIO; | 5421 | err = -EIO; |
5413 | } | 5422 | } |
5414 | brelse(iloc.bh); | 5423 | brelse(iloc.bh); |
@@ -5483,10 +5492,8 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) | |||
5483 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { | 5492 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) { |
5484 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); | 5493 | struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
5485 | 5494 | ||
5486 | if (attr->ia_size > sbi->s_bitmap_maxbytes) { | 5495 | if (attr->ia_size > sbi->s_bitmap_maxbytes) |
5487 | error = -EFBIG; | 5496 | return -EFBIG; |
5488 | goto err_out; | ||
5489 | } | ||
5490 | } | 5497 | } |
5491 | } | 5498 | } |
5492 | 5499 | ||
@@ -5688,7 +5695,7 @@ int ext4_writepage_trans_blocks(struct inode *inode) | |||
5688 | * Calculate the journal credits for a chunk of data modification. | 5695 | * Calculate the journal credits for a chunk of data modification. |
5689 | * | 5696 | * |
5690 | * This is called from DIO, fallocate or whoever calling | 5697 | * This is called from DIO, fallocate or whoever calling |
5691 | * ext4_get_blocks() to map/allocate a chunk of contiguous disk blocks. | 5698 | * ext4_map_blocks() to map/allocate a chunk of contiguous disk blocks. |
5692 | * | 5699 | * |
5693 | * journal buffers for data blocks are not included here, as DIO | 5700 | * journal buffers for data blocks are not included here, as DIO |
5694 | * and fallocate do no need to journal data buffers. | 5701 | * and fallocate do no need to journal data buffers. |
@@ -5754,7 +5761,6 @@ static int ext4_expand_extra_isize(struct inode *inode, | |||
5754 | { | 5761 | { |
5755 | struct ext4_inode *raw_inode; | 5762 | struct ext4_inode *raw_inode; |
5756 | struct ext4_xattr_ibody_header *header; | 5763 | struct ext4_xattr_ibody_header *header; |
5757 | struct ext4_xattr_entry *entry; | ||
5758 | 5764 | ||
5759 | if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) | 5765 | if (EXT4_I(inode)->i_extra_isize >= new_extra_isize) |
5760 | return 0; | 5766 | return 0; |
@@ -5762,7 +5768,6 @@ static int ext4_expand_extra_isize(struct inode *inode, | |||
5762 | raw_inode = ext4_raw_inode(&iloc); | 5768 | raw_inode = ext4_raw_inode(&iloc); |
5763 | 5769 | ||
5764 | header = IHDR(inode, raw_inode); | 5770 | header = IHDR(inode, raw_inode); |
5765 | entry = IFIRST(header); | ||
5766 | 5771 | ||
5767 | /* No extended attributes present */ | 5772 | /* No extended attributes present */ |
5768 | if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) || | 5773 | if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR) || |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 12b3bc026a68..4b4ad4b7ce57 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -446,10 +446,11 @@ static void mb_free_blocks_double(struct inode *inode, struct ext4_buddy *e4b, | |||
446 | blocknr = ext4_group_first_block_no(sb, e4b->bd_group); | 446 | blocknr = ext4_group_first_block_no(sb, e4b->bd_group); |
447 | blocknr += first + i; | 447 | blocknr += first + i; |
448 | ext4_grp_locked_error(sb, e4b->bd_group, | 448 | ext4_grp_locked_error(sb, e4b->bd_group, |
449 | __func__, "double-free of inode" | 449 | inode ? inode->i_ino : 0, |
450 | " %lu's block %llu(bit %u in group %u)", | 450 | blocknr, |
451 | inode ? inode->i_ino : 0, blocknr, | 451 | "freeing block already freed " |
452 | first + i, e4b->bd_group); | 452 | "(bit %u)", |
453 | first + i); | ||
453 | } | 454 | } |
454 | mb_clear_bit(first + i, e4b->bd_info->bb_bitmap); | 455 | mb_clear_bit(first + i, e4b->bd_info->bb_bitmap); |
455 | } | 456 | } |
@@ -712,9 +713,9 @@ void ext4_mb_generate_buddy(struct super_block *sb, | |||
712 | grp->bb_fragments = fragments; | 713 | grp->bb_fragments = fragments; |
713 | 714 | ||
714 | if (free != grp->bb_free) { | 715 | if (free != grp->bb_free) { |
715 | ext4_grp_locked_error(sb, group, __func__, | 716 | ext4_grp_locked_error(sb, group, 0, 0, |
716 | "EXT4-fs: group %u: %u blocks in bitmap, %u in gd", | 717 | "%u blocks in bitmap, %u in gd", |
717 | group, free, grp->bb_free); | 718 | free, grp->bb_free); |
718 | /* | 719 | /* |
719 | * If we intent to continue, we consider group descritor | 720 | * If we intent to continue, we consider group descritor |
720 | * corrupt and update bb_free using bitmap value | 721 | * corrupt and update bb_free using bitmap value |
@@ -1296,10 +1297,10 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, | |||
1296 | blocknr = ext4_group_first_block_no(sb, e4b->bd_group); | 1297 | blocknr = ext4_group_first_block_no(sb, e4b->bd_group); |
1297 | blocknr += block; | 1298 | blocknr += block; |
1298 | ext4_grp_locked_error(sb, e4b->bd_group, | 1299 | ext4_grp_locked_error(sb, e4b->bd_group, |
1299 | __func__, "double-free of inode" | 1300 | inode ? inode->i_ino : 0, |
1300 | " %lu's block %llu(bit %u in group %u)", | 1301 | blocknr, |
1301 | inode ? inode->i_ino : 0, blocknr, block, | 1302 | "freeing already freed block " |
1302 | e4b->bd_group); | 1303 | "(bit %u)", block); |
1303 | } | 1304 | } |
1304 | mb_clear_bit(block, EXT4_MB_BITMAP(e4b)); | 1305 | mb_clear_bit(block, EXT4_MB_BITMAP(e4b)); |
1305 | e4b->bd_info->bb_counters[order]++; | 1306 | e4b->bd_info->bb_counters[order]++; |
@@ -1788,8 +1789,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | |||
1788 | * free blocks even though group info says we | 1789 | * free blocks even though group info says we |
1789 | * we have free blocks | 1790 | * we have free blocks |
1790 | */ | 1791 | */ |
1791 | ext4_grp_locked_error(sb, e4b->bd_group, | 1792 | ext4_grp_locked_error(sb, e4b->bd_group, 0, 0, |
1792 | __func__, "%d free blocks as per " | 1793 | "%d free blocks as per " |
1793 | "group info. But bitmap says 0", | 1794 | "group info. But bitmap says 0", |
1794 | free); | 1795 | free); |
1795 | break; | 1796 | break; |
@@ -1798,8 +1799,8 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | |||
1798 | mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex); | 1799 | mb_find_extent(e4b, 0, i, ac->ac_g_ex.fe_len, &ex); |
1799 | BUG_ON(ex.fe_len <= 0); | 1800 | BUG_ON(ex.fe_len <= 0); |
1800 | if (free < ex.fe_len) { | 1801 | if (free < ex.fe_len) { |
1801 | ext4_grp_locked_error(sb, e4b->bd_group, | 1802 | ext4_grp_locked_error(sb, e4b->bd_group, 0, 0, |
1802 | __func__, "%d free blocks as per " | 1803 | "%d free blocks as per " |
1803 | "group info. But got %d blocks", | 1804 | "group info. But got %d blocks", |
1804 | free, ex.fe_len); | 1805 | free, ex.fe_len); |
1805 | /* | 1806 | /* |
@@ -1821,8 +1822,7 @@ void ext4_mb_complex_scan_group(struct ext4_allocation_context *ac, | |||
1821 | 1822 | ||
1822 | /* | 1823 | /* |
1823 | * This is a special case for storages like raid5 | 1824 | * This is a special case for storages like raid5 |
1824 | * we try to find stripe-aligned chunks for stripe-size requests | 1825 | * we try to find stripe-aligned chunks for stripe-size-multiple requests |
1825 | * XXX should do so at least for multiples of stripe size as well | ||
1826 | */ | 1826 | */ |
1827 | static noinline_for_stack | 1827 | static noinline_for_stack |
1828 | void ext4_mb_scan_aligned(struct ext4_allocation_context *ac, | 1828 | void ext4_mb_scan_aligned(struct ext4_allocation_context *ac, |
@@ -1999,7 +1999,6 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac) | |||
1999 | ext4_group_t ngroups, group, i; | 1999 | ext4_group_t ngroups, group, i; |
2000 | int cr; | 2000 | int cr; |
2001 | int err = 0; | 2001 | int err = 0; |
2002 | int bsbits; | ||
2003 | struct ext4_sb_info *sbi; | 2002 | struct ext4_sb_info *sbi; |
2004 | struct super_block *sb; | 2003 | struct super_block *sb; |
2005 | struct ext4_buddy e4b; | 2004 | struct ext4_buddy e4b; |
@@ -2041,8 +2040,6 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac) | |||
2041 | ac->ac_2order = i - 1; | 2040 | ac->ac_2order = i - 1; |
2042 | } | 2041 | } |
2043 | 2042 | ||
2044 | bsbits = ac->ac_sb->s_blocksize_bits; | ||
2045 | |||
2046 | /* if stream allocation is enabled, use global goal */ | 2043 | /* if stream allocation is enabled, use global goal */ |
2047 | if (ac->ac_flags & EXT4_MB_STREAM_ALLOC) { | 2044 | if (ac->ac_flags & EXT4_MB_STREAM_ALLOC) { |
2048 | /* TBD: may be hot point */ | 2045 | /* TBD: may be hot point */ |
@@ -2094,8 +2091,8 @@ repeat: | |||
2094 | ac->ac_groups_scanned++; | 2091 | ac->ac_groups_scanned++; |
2095 | if (cr == 0) | 2092 | if (cr == 0) |
2096 | ext4_mb_simple_scan_group(ac, &e4b); | 2093 | ext4_mb_simple_scan_group(ac, &e4b); |
2097 | else if (cr == 1 && | 2094 | else if (cr == 1 && sbi->s_stripe && |
2098 | ac->ac_g_ex.fe_len == sbi->s_stripe) | 2095 | !(ac->ac_g_ex.fe_len % sbi->s_stripe)) |
2099 | ext4_mb_scan_aligned(ac, &e4b); | 2096 | ext4_mb_scan_aligned(ac, &e4b); |
2100 | else | 2097 | else |
2101 | ext4_mb_complex_scan_group(ac, &e4b); | 2098 | ext4_mb_complex_scan_group(ac, &e4b); |
@@ -2221,7 +2218,7 @@ static int ext4_mb_seq_groups_open(struct inode *inode, struct file *file) | |||
2221 | 2218 | ||
2222 | rc = seq_open(file, &ext4_mb_seq_groups_ops); | 2219 | rc = seq_open(file, &ext4_mb_seq_groups_ops); |
2223 | if (rc == 0) { | 2220 | if (rc == 0) { |
2224 | struct seq_file *m = (struct seq_file *)file->private_data; | 2221 | struct seq_file *m = file->private_data; |
2225 | m->private = sb; | 2222 | m->private = sb; |
2226 | } | 2223 | } |
2227 | return rc; | 2224 | return rc; |
@@ -2560,6 +2557,22 @@ int ext4_mb_release(struct super_block *sb) | |||
2560 | return 0; | 2557 | return 0; |
2561 | } | 2558 | } |
2562 | 2559 | ||
2560 | static inline void ext4_issue_discard(struct super_block *sb, | ||
2561 | ext4_group_t block_group, ext4_grpblk_t block, int count) | ||
2562 | { | ||
2563 | int ret; | ||
2564 | ext4_fsblk_t discard_block; | ||
2565 | |||
2566 | discard_block = block + ext4_group_first_block_no(sb, block_group); | ||
2567 | trace_ext4_discard_blocks(sb, | ||
2568 | (unsigned long long) discard_block, count); | ||
2569 | ret = sb_issue_discard(sb, discard_block, count); | ||
2570 | if (ret == EOPNOTSUPP) { | ||
2571 | ext4_warning(sb, "discard not supported, disabling"); | ||
2572 | clear_opt(EXT4_SB(sb)->s_mount_opt, DISCARD); | ||
2573 | } | ||
2574 | } | ||
2575 | |||
2563 | /* | 2576 | /* |
2564 | * This function is called by the jbd2 layer once the commit has finished, | 2577 | * This function is called by the jbd2 layer once the commit has finished, |
2565 | * so we know we can free the blocks that were released with that commit. | 2578 | * so we know we can free the blocks that were released with that commit. |
@@ -2579,22 +2592,9 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) | |||
2579 | mb_debug(1, "gonna free %u blocks in group %u (0x%p):", | 2592 | mb_debug(1, "gonna free %u blocks in group %u (0x%p):", |
2580 | entry->count, entry->group, entry); | 2593 | entry->count, entry->group, entry); |
2581 | 2594 | ||
2582 | if (test_opt(sb, DISCARD)) { | 2595 | if (test_opt(sb, DISCARD)) |
2583 | int ret; | 2596 | ext4_issue_discard(sb, entry->group, |
2584 | ext4_fsblk_t discard_block; | 2597 | entry->start_blk, entry->count); |
2585 | |||
2586 | discard_block = entry->start_blk + | ||
2587 | ext4_group_first_block_no(sb, entry->group); | ||
2588 | trace_ext4_discard_blocks(sb, | ||
2589 | (unsigned long long)discard_block, | ||
2590 | entry->count); | ||
2591 | ret = sb_issue_discard(sb, discard_block, entry->count); | ||
2592 | if (ret == EOPNOTSUPP) { | ||
2593 | ext4_warning(sb, | ||
2594 | "discard not supported, disabling"); | ||
2595 | clear_opt(EXT4_SB(sb)->s_mount_opt, DISCARD); | ||
2596 | } | ||
2597 | } | ||
2598 | 2598 | ||
2599 | err = ext4_mb_load_buddy(sb, entry->group, &e4b); | 2599 | err = ext4_mb_load_buddy(sb, entry->group, &e4b); |
2600 | /* we expect to find existing buddy because it's pinned */ | 2600 | /* we expect to find existing buddy because it's pinned */ |
@@ -2704,7 +2704,7 @@ void exit_ext4_mballoc(void) | |||
2704 | 2704 | ||
2705 | 2705 | ||
2706 | /* | 2706 | /* |
2707 | * Check quota and mark choosed space (ac->ac_b_ex) non-free in bitmaps | 2707 | * Check quota and mark chosen space (ac->ac_b_ex) non-free in bitmaps |
2708 | * Returns 0 if success or error code | 2708 | * Returns 0 if success or error code |
2709 | */ | 2709 | */ |
2710 | static noinline_for_stack int | 2710 | static noinline_for_stack int |
@@ -2712,7 +2712,6 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
2712 | handle_t *handle, unsigned int reserv_blks) | 2712 | handle_t *handle, unsigned int reserv_blks) |
2713 | { | 2713 | { |
2714 | struct buffer_head *bitmap_bh = NULL; | 2714 | struct buffer_head *bitmap_bh = NULL; |
2715 | struct ext4_super_block *es; | ||
2716 | struct ext4_group_desc *gdp; | 2715 | struct ext4_group_desc *gdp; |
2717 | struct buffer_head *gdp_bh; | 2716 | struct buffer_head *gdp_bh; |
2718 | struct ext4_sb_info *sbi; | 2717 | struct ext4_sb_info *sbi; |
@@ -2725,8 +2724,6 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
2725 | 2724 | ||
2726 | sb = ac->ac_sb; | 2725 | sb = ac->ac_sb; |
2727 | sbi = EXT4_SB(sb); | 2726 | sbi = EXT4_SB(sb); |
2728 | es = sbi->s_es; | ||
2729 | |||
2730 | 2727 | ||
2731 | err = -EIO; | 2728 | err = -EIO; |
2732 | bitmap_bh = ext4_read_block_bitmap(sb, ac->ac_b_ex.fe_group); | 2729 | bitmap_bh = ext4_read_block_bitmap(sb, ac->ac_b_ex.fe_group); |
@@ -2812,7 +2809,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
2812 | err = ext4_handle_dirty_metadata(handle, NULL, gdp_bh); | 2809 | err = ext4_handle_dirty_metadata(handle, NULL, gdp_bh); |
2813 | 2810 | ||
2814 | out_err: | 2811 | out_err: |
2815 | sb->s_dirt = 1; | 2812 | ext4_mark_super_dirty(sb); |
2816 | brelse(bitmap_bh); | 2813 | brelse(bitmap_bh); |
2817 | return err; | 2814 | return err; |
2818 | } | 2815 | } |
@@ -2850,7 +2847,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, | |||
2850 | int bsbits, max; | 2847 | int bsbits, max; |
2851 | ext4_lblk_t end; | 2848 | ext4_lblk_t end; |
2852 | loff_t size, orig_size, start_off; | 2849 | loff_t size, orig_size, start_off; |
2853 | ext4_lblk_t start, orig_start; | 2850 | ext4_lblk_t start; |
2854 | struct ext4_inode_info *ei = EXT4_I(ac->ac_inode); | 2851 | struct ext4_inode_info *ei = EXT4_I(ac->ac_inode); |
2855 | struct ext4_prealloc_space *pa; | 2852 | struct ext4_prealloc_space *pa; |
2856 | 2853 | ||
@@ -2881,6 +2878,7 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, | |||
2881 | size = size << bsbits; | 2878 | size = size << bsbits; |
2882 | if (size < i_size_read(ac->ac_inode)) | 2879 | if (size < i_size_read(ac->ac_inode)) |
2883 | size = i_size_read(ac->ac_inode); | 2880 | size = i_size_read(ac->ac_inode); |
2881 | orig_size = size; | ||
2884 | 2882 | ||
2885 | /* max size of free chunks */ | 2883 | /* max size of free chunks */ |
2886 | max = 2 << bsbits; | 2884 | max = 2 << bsbits; |
@@ -2922,8 +2920,8 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, | |||
2922 | start_off = (loff_t)ac->ac_o_ex.fe_logical << bsbits; | 2920 | start_off = (loff_t)ac->ac_o_ex.fe_logical << bsbits; |
2923 | size = ac->ac_o_ex.fe_len << bsbits; | 2921 | size = ac->ac_o_ex.fe_len << bsbits; |
2924 | } | 2922 | } |
2925 | orig_size = size = size >> bsbits; | 2923 | size = size >> bsbits; |
2926 | orig_start = start = start_off >> bsbits; | 2924 | start = start_off >> bsbits; |
2927 | 2925 | ||
2928 | /* don't cover already allocated blocks in selected range */ | 2926 | /* don't cover already allocated blocks in selected range */ |
2929 | if (ar->pleft && start <= ar->lleft) { | 2927 | if (ar->pleft && start <= ar->lleft) { |
@@ -3547,7 +3545,6 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh, | |||
3547 | ext4_group_t group; | 3545 | ext4_group_t group; |
3548 | ext4_grpblk_t bit; | 3546 | ext4_grpblk_t bit; |
3549 | unsigned long long grp_blk_start; | 3547 | unsigned long long grp_blk_start; |
3550 | sector_t start; | ||
3551 | int err = 0; | 3548 | int err = 0; |
3552 | int free = 0; | 3549 | int free = 0; |
3553 | 3550 | ||
@@ -3567,10 +3564,9 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh, | |||
3567 | if (bit >= end) | 3564 | if (bit >= end) |
3568 | break; | 3565 | break; |
3569 | next = mb_find_next_bit(bitmap_bh->b_data, end, bit); | 3566 | next = mb_find_next_bit(bitmap_bh->b_data, end, bit); |
3570 | start = ext4_group_first_block_no(sb, group) + bit; | ||
3571 | mb_debug(1, " free preallocated %u/%u in group %u\n", | 3567 | mb_debug(1, " free preallocated %u/%u in group %u\n", |
3572 | (unsigned) start, (unsigned) next - bit, | 3568 | (unsigned) ext4_group_first_block_no(sb, group) + bit, |
3573 | (unsigned) group); | 3569 | (unsigned) next - bit, (unsigned) group); |
3574 | free += next - bit; | 3570 | free += next - bit; |
3575 | 3571 | ||
3576 | if (ac) { | 3572 | if (ac) { |
@@ -3581,7 +3577,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh, | |||
3581 | trace_ext4_mballoc_discard(ac); | 3577 | trace_ext4_mballoc_discard(ac); |
3582 | } | 3578 | } |
3583 | 3579 | ||
3584 | trace_ext4_mb_release_inode_pa(ac, pa, grp_blk_start + bit, | 3580 | trace_ext4_mb_release_inode_pa(sb, ac, pa, grp_blk_start + bit, |
3585 | next - bit); | 3581 | next - bit); |
3586 | mb_free_blocks(pa->pa_inode, e4b, bit, next - bit); | 3582 | mb_free_blocks(pa->pa_inode, e4b, bit, next - bit); |
3587 | bit = next + 1; | 3583 | bit = next + 1; |
@@ -3591,8 +3587,7 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh, | |||
3591 | pa, (unsigned long) pa->pa_lstart, | 3587 | pa, (unsigned long) pa->pa_lstart, |
3592 | (unsigned long) pa->pa_pstart, | 3588 | (unsigned long) pa->pa_pstart, |
3593 | (unsigned long) pa->pa_len); | 3589 | (unsigned long) pa->pa_len); |
3594 | ext4_grp_locked_error(sb, group, | 3590 | ext4_grp_locked_error(sb, group, 0, 0, "free %u, pa_free %u", |
3595 | __func__, "free %u, pa_free %u", | ||
3596 | free, pa->pa_free); | 3591 | free, pa->pa_free); |
3597 | /* | 3592 | /* |
3598 | * pa is already deleted so we use the value obtained | 3593 | * pa is already deleted so we use the value obtained |
@@ -3613,7 +3608,7 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b, | |||
3613 | ext4_group_t group; | 3608 | ext4_group_t group; |
3614 | ext4_grpblk_t bit; | 3609 | ext4_grpblk_t bit; |
3615 | 3610 | ||
3616 | trace_ext4_mb_release_group_pa(ac, pa); | 3611 | trace_ext4_mb_release_group_pa(sb, ac, pa); |
3617 | BUG_ON(pa->pa_deleted == 0); | 3612 | BUG_ON(pa->pa_deleted == 0); |
3618 | ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit); | 3613 | ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit); |
3619 | BUG_ON(group != e4b->bd_group && pa->pa_len != 0); | 3614 | BUG_ON(group != e4b->bd_group && pa->pa_len != 0); |
@@ -3889,6 +3884,9 @@ static void ext4_mb_show_ac(struct ext4_allocation_context *ac) | |||
3889 | struct super_block *sb = ac->ac_sb; | 3884 | struct super_block *sb = ac->ac_sb; |
3890 | ext4_group_t ngroups, i; | 3885 | ext4_group_t ngroups, i; |
3891 | 3886 | ||
3887 | if (EXT4_SB(sb)->s_mount_flags & EXT4_MF_FS_ABORTED) | ||
3888 | return; | ||
3889 | |||
3892 | printk(KERN_ERR "EXT4-fs: Can't allocate:" | 3890 | printk(KERN_ERR "EXT4-fs: Can't allocate:" |
3893 | " Allocation context details:\n"); | 3891 | " Allocation context details:\n"); |
3894 | printk(KERN_ERR "EXT4-fs: status %d flags %d\n", | 3892 | printk(KERN_ERR "EXT4-fs: status %d flags %d\n", |
@@ -4255,7 +4253,7 @@ static int ext4_mb_discard_preallocations(struct super_block *sb, int needed) | |||
4255 | * to usual allocation | 4253 | * to usual allocation |
4256 | */ | 4254 | */ |
4257 | ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | 4255 | ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, |
4258 | struct ext4_allocation_request *ar, int *errp) | 4256 | struct ext4_allocation_request *ar, int *errp) |
4259 | { | 4257 | { |
4260 | int freed; | 4258 | int freed; |
4261 | struct ext4_allocation_context *ac = NULL; | 4259 | struct ext4_allocation_context *ac = NULL; |
@@ -4299,7 +4297,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | |||
4299 | inquota = ar->len; | 4297 | inquota = ar->len; |
4300 | if (ar->len == 0) { | 4298 | if (ar->len == 0) { |
4301 | *errp = -EDQUOT; | 4299 | *errp = -EDQUOT; |
4302 | goto out3; | 4300 | goto out; |
4303 | } | 4301 | } |
4304 | } | 4302 | } |
4305 | 4303 | ||
@@ -4307,13 +4305,13 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | |||
4307 | if (!ac) { | 4305 | if (!ac) { |
4308 | ar->len = 0; | 4306 | ar->len = 0; |
4309 | *errp = -ENOMEM; | 4307 | *errp = -ENOMEM; |
4310 | goto out1; | 4308 | goto out; |
4311 | } | 4309 | } |
4312 | 4310 | ||
4313 | *errp = ext4_mb_initialize_context(ac, ar); | 4311 | *errp = ext4_mb_initialize_context(ac, ar); |
4314 | if (*errp) { | 4312 | if (*errp) { |
4315 | ar->len = 0; | 4313 | ar->len = 0; |
4316 | goto out2; | 4314 | goto out; |
4317 | } | 4315 | } |
4318 | 4316 | ||
4319 | ac->ac_op = EXT4_MB_HISTORY_PREALLOC; | 4317 | ac->ac_op = EXT4_MB_HISTORY_PREALLOC; |
@@ -4322,7 +4320,9 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | |||
4322 | ext4_mb_normalize_request(ac, ar); | 4320 | ext4_mb_normalize_request(ac, ar); |
4323 | repeat: | 4321 | repeat: |
4324 | /* allocate space in core */ | 4322 | /* allocate space in core */ |
4325 | ext4_mb_regular_allocator(ac); | 4323 | *errp = ext4_mb_regular_allocator(ac); |
4324 | if (*errp) | ||
4325 | goto errout; | ||
4326 | 4326 | ||
4327 | /* as we've just preallocated more space than | 4327 | /* as we've just preallocated more space than |
4328 | * user requested orinally, we store allocated | 4328 | * user requested orinally, we store allocated |
@@ -4333,7 +4333,7 @@ repeat: | |||
4333 | } | 4333 | } |
4334 | if (likely(ac->ac_status == AC_STATUS_FOUND)) { | 4334 | if (likely(ac->ac_status == AC_STATUS_FOUND)) { |
4335 | *errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_blks); | 4335 | *errp = ext4_mb_mark_diskspace_used(ac, handle, reserv_blks); |
4336 | if (*errp == -EAGAIN) { | 4336 | if (*errp == -EAGAIN) { |
4337 | /* | 4337 | /* |
4338 | * drop the reference that we took | 4338 | * drop the reference that we took |
4339 | * in ext4_mb_use_best_found | 4339 | * in ext4_mb_use_best_found |
@@ -4344,12 +4344,10 @@ repeat: | |||
4344 | ac->ac_b_ex.fe_len = 0; | 4344 | ac->ac_b_ex.fe_len = 0; |
4345 | ac->ac_status = AC_STATUS_CONTINUE; | 4345 | ac->ac_status = AC_STATUS_CONTINUE; |
4346 | goto repeat; | 4346 | goto repeat; |
4347 | } else if (*errp) { | 4347 | } else if (*errp) |
4348 | errout: | ||
4348 | ext4_discard_allocated_blocks(ac); | 4349 | ext4_discard_allocated_blocks(ac); |
4349 | ac->ac_b_ex.fe_len = 0; | 4350 | else { |
4350 | ar->len = 0; | ||
4351 | ext4_mb_show_ac(ac); | ||
4352 | } else { | ||
4353 | block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); | 4351 | block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); |
4354 | ar->len = ac->ac_b_ex.fe_len; | 4352 | ar->len = ac->ac_b_ex.fe_len; |
4355 | } | 4353 | } |
@@ -4358,19 +4356,19 @@ repeat: | |||
4358 | if (freed) | 4356 | if (freed) |
4359 | goto repeat; | 4357 | goto repeat; |
4360 | *errp = -ENOSPC; | 4358 | *errp = -ENOSPC; |
4359 | } | ||
4360 | |||
4361 | if (*errp) { | ||
4361 | ac->ac_b_ex.fe_len = 0; | 4362 | ac->ac_b_ex.fe_len = 0; |
4362 | ar->len = 0; | 4363 | ar->len = 0; |
4363 | ext4_mb_show_ac(ac); | 4364 | ext4_mb_show_ac(ac); |
4364 | } | 4365 | } |
4365 | |||
4366 | ext4_mb_release_context(ac); | 4366 | ext4_mb_release_context(ac); |
4367 | 4367 | out: | |
4368 | out2: | 4368 | if (ac) |
4369 | kmem_cache_free(ext4_ac_cachep, ac); | 4369 | kmem_cache_free(ext4_ac_cachep, ac); |
4370 | out1: | ||
4371 | if (inquota && ar->len < inquota) | 4370 | if (inquota && ar->len < inquota) |
4372 | dquot_free_block(ar->inode, inquota - ar->len); | 4371 | dquot_free_block(ar->inode, inquota - ar->len); |
4373 | out3: | ||
4374 | if (!ar->len) { | 4372 | if (!ar->len) { |
4375 | if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag) | 4373 | if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag) |
4376 | /* release all the reserved blocks if non delalloc */ | 4374 | /* release all the reserved blocks if non delalloc */ |
@@ -4402,6 +4400,7 @@ static noinline_for_stack int | |||
4402 | ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, | 4400 | ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, |
4403 | struct ext4_free_data *new_entry) | 4401 | struct ext4_free_data *new_entry) |
4404 | { | 4402 | { |
4403 | ext4_group_t group = e4b->bd_group; | ||
4405 | ext4_grpblk_t block; | 4404 | ext4_grpblk_t block; |
4406 | struct ext4_free_data *entry; | 4405 | struct ext4_free_data *entry; |
4407 | struct ext4_group_info *db = e4b->bd_info; | 4406 | struct ext4_group_info *db = e4b->bd_info; |
@@ -4434,9 +4433,9 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, | |||
4434 | else if (block >= (entry->start_blk + entry->count)) | 4433 | else if (block >= (entry->start_blk + entry->count)) |
4435 | n = &(*n)->rb_right; | 4434 | n = &(*n)->rb_right; |
4436 | else { | 4435 | else { |
4437 | ext4_grp_locked_error(sb, e4b->bd_group, __func__, | 4436 | ext4_grp_locked_error(sb, group, 0, |
4438 | "Double free of blocks %d (%d %d)", | 4437 | ext4_group_first_block_no(sb, group) + block, |
4439 | block, entry->start_blk, entry->count); | 4438 | "Block already on to-be-freed list"); |
4440 | return 0; | 4439 | return 0; |
4441 | } | 4440 | } |
4442 | } | 4441 | } |
@@ -4494,7 +4493,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, | |||
4494 | struct super_block *sb = inode->i_sb; | 4493 | struct super_block *sb = inode->i_sb; |
4495 | struct ext4_allocation_context *ac = NULL; | 4494 | struct ext4_allocation_context *ac = NULL; |
4496 | struct ext4_group_desc *gdp; | 4495 | struct ext4_group_desc *gdp; |
4497 | struct ext4_super_block *es; | ||
4498 | unsigned long freed = 0; | 4496 | unsigned long freed = 0; |
4499 | unsigned int overflow; | 4497 | unsigned int overflow; |
4500 | ext4_grpblk_t bit; | 4498 | ext4_grpblk_t bit; |
@@ -4513,7 +4511,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, | |||
4513 | } | 4511 | } |
4514 | 4512 | ||
4515 | sbi = EXT4_SB(sb); | 4513 | sbi = EXT4_SB(sb); |
4516 | es = EXT4_SB(sb)->s_es; | ||
4517 | if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) && | 4514 | if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) && |
4518 | !ext4_data_block_valid(sbi, block, count)) { | 4515 | !ext4_data_block_valid(sbi, block, count)) { |
4519 | ext4_error(sb, "Freeing blocks not in datazone - " | 4516 | ext4_error(sb, "Freeing blocks not in datazone - " |
@@ -4647,6 +4644,8 @@ do_more: | |||
4647 | mb_clear_bits(bitmap_bh->b_data, bit, count); | 4644 | mb_clear_bits(bitmap_bh->b_data, bit, count); |
4648 | mb_free_blocks(inode, &e4b, bit, count); | 4645 | mb_free_blocks(inode, &e4b, bit, count); |
4649 | ext4_mb_return_to_preallocation(inode, &e4b, block, count); | 4646 | ext4_mb_return_to_preallocation(inode, &e4b, block, count); |
4647 | if (test_opt(sb, DISCARD)) | ||
4648 | ext4_issue_discard(sb, block_group, bit, count); | ||
4650 | } | 4649 | } |
4651 | 4650 | ||
4652 | ret = ext4_free_blks_count(sb, gdp) + count; | 4651 | ret = ext4_free_blks_count(sb, gdp) + count; |
@@ -4680,7 +4679,7 @@ do_more: | |||
4680 | put_bh(bitmap_bh); | 4679 | put_bh(bitmap_bh); |
4681 | goto do_more; | 4680 | goto do_more; |
4682 | } | 4681 | } |
4683 | sb->s_dirt = 1; | 4682 | ext4_mark_super_dirty(sb); |
4684 | error_return: | 4683 | error_return: |
4685 | if (freed) | 4684 | if (freed) |
4686 | dquot_free_block(inode, freed); | 4685 | dquot_free_block(inode, freed); |
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index 6f3a27ec30bf..1765c2c50a9b 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c | |||
@@ -376,7 +376,7 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode, | |||
376 | * We have the extent map build with the tmp inode. | 376 | * We have the extent map build with the tmp inode. |
377 | * Now copy the i_data across | 377 | * Now copy the i_data across |
378 | */ | 378 | */ |
379 | ei->i_flags |= EXT4_EXTENTS_FL; | 379 | ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS); |
380 | memcpy(ei->i_data, tmp_ei->i_data, sizeof(ei->i_data)); | 380 | memcpy(ei->i_data, tmp_ei->i_data, sizeof(ei->i_data)); |
381 | 381 | ||
382 | /* | 382 | /* |
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 52abfa12762a..5f1ed9fc913c 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
@@ -148,17 +148,17 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path, | |||
148 | */ | 148 | */ |
149 | static int | 149 | static int |
150 | mext_check_null_inode(struct inode *inode1, struct inode *inode2, | 150 | mext_check_null_inode(struct inode *inode1, struct inode *inode2, |
151 | const char *function) | 151 | const char *function, unsigned int line) |
152 | { | 152 | { |
153 | int ret = 0; | 153 | int ret = 0; |
154 | 154 | ||
155 | if (inode1 == NULL) { | 155 | if (inode1 == NULL) { |
156 | __ext4_error(inode2->i_sb, function, | 156 | __ext4_error(inode2->i_sb, function, line, |
157 | "Both inodes should not be NULL: " | 157 | "Both inodes should not be NULL: " |
158 | "inode1 NULL inode2 %lu", inode2->i_ino); | 158 | "inode1 NULL inode2 %lu", inode2->i_ino); |
159 | ret = -EIO; | 159 | ret = -EIO; |
160 | } else if (inode2 == NULL) { | 160 | } else if (inode2 == NULL) { |
161 | __ext4_error(inode1->i_sb, function, | 161 | __ext4_error(inode1->i_sb, function, line, |
162 | "Both inodes should not be NULL: " | 162 | "Both inodes should not be NULL: " |
163 | "inode1 %lu inode2 NULL", inode1->i_ino); | 163 | "inode1 %lu inode2 NULL", inode1->i_ino); |
164 | ret = -EIO; | 164 | ret = -EIO; |
@@ -1084,7 +1084,7 @@ mext_inode_double_lock(struct inode *inode1, struct inode *inode2) | |||
1084 | 1084 | ||
1085 | BUG_ON(inode1 == NULL && inode2 == NULL); | 1085 | BUG_ON(inode1 == NULL && inode2 == NULL); |
1086 | 1086 | ||
1087 | ret = mext_check_null_inode(inode1, inode2, __func__); | 1087 | ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__); |
1088 | if (ret < 0) | 1088 | if (ret < 0) |
1089 | goto out; | 1089 | goto out; |
1090 | 1090 | ||
@@ -1121,7 +1121,7 @@ mext_inode_double_unlock(struct inode *inode1, struct inode *inode2) | |||
1121 | 1121 | ||
1122 | BUG_ON(inode1 == NULL && inode2 == NULL); | 1122 | BUG_ON(inode1 == NULL && inode2 == NULL); |
1123 | 1123 | ||
1124 | ret = mext_check_null_inode(inode1, inode2, __func__); | 1124 | ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__); |
1125 | if (ret < 0) | 1125 | if (ret < 0) |
1126 | goto out; | 1126 | goto out; |
1127 | 1127 | ||
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index a43e6617b351..314c0d3b3fa9 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
@@ -179,30 +179,6 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, | |||
179 | static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, | 179 | static int ext4_dx_add_entry(handle_t *handle, struct dentry *dentry, |
180 | struct inode *inode); | 180 | struct inode *inode); |
181 | 181 | ||
182 | unsigned int ext4_rec_len_from_disk(__le16 dlen, unsigned blocksize) | ||
183 | { | ||
184 | unsigned len = le16_to_cpu(dlen); | ||
185 | |||
186 | if (len == EXT4_MAX_REC_LEN || len == 0) | ||
187 | return blocksize; | ||
188 | return (len & 65532) | ((len & 3) << 16); | ||
189 | } | ||
190 | |||
191 | __le16 ext4_rec_len_to_disk(unsigned len, unsigned blocksize) | ||
192 | { | ||
193 | if ((len > blocksize) || (blocksize > (1 << 18)) || (len & 3)) | ||
194 | BUG(); | ||
195 | if (len < 65536) | ||
196 | return cpu_to_le16(len); | ||
197 | if (len == blocksize) { | ||
198 | if (blocksize == 65536) | ||
199 | return cpu_to_le16(EXT4_MAX_REC_LEN); | ||
200 | else | ||
201 | return cpu_to_le16(0); | ||
202 | } | ||
203 | return cpu_to_le16((len & 65532) | ((len >> 16) & 3)); | ||
204 | } | ||
205 | |||
206 | /* | 182 | /* |
207 | * p is at least 6 bytes before the end of page | 183 | * p is at least 6 bytes before the end of page |
208 | */ | 184 | */ |
@@ -605,7 +581,7 @@ static int htree_dirblock_to_tree(struct file *dir_file, | |||
605 | dir->i_sb->s_blocksize - | 581 | dir->i_sb->s_blocksize - |
606 | EXT4_DIR_REC_LEN(0)); | 582 | EXT4_DIR_REC_LEN(0)); |
607 | for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) { | 583 | for (; de < top; de = ext4_next_entry(de, dir->i_sb->s_blocksize)) { |
608 | if (!ext4_check_dir_entry("htree_dirblock_to_tree", dir, de, bh, | 584 | if (!ext4_check_dir_entry(dir, de, bh, |
609 | (block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb)) | 585 | (block<<EXT4_BLOCK_SIZE_BITS(dir->i_sb)) |
610 | +((char *)de - bh->b_data))) { | 586 | +((char *)de - bh->b_data))) { |
611 | /* On error, skip the f_pos to the next block. */ | 587 | /* On error, skip the f_pos to the next block. */ |
@@ -844,8 +820,7 @@ static inline int search_dirblock(struct buffer_head *bh, | |||
844 | if ((char *) de + namelen <= dlimit && | 820 | if ((char *) de + namelen <= dlimit && |
845 | ext4_match (namelen, name, de)) { | 821 | ext4_match (namelen, name, de)) { |
846 | /* found a match - just to be sure, do a full check */ | 822 | /* found a match - just to be sure, do a full check */ |
847 | if (!ext4_check_dir_entry("ext4_find_entry", | 823 | if (!ext4_check_dir_entry(dir, de, bh, offset)) |
848 | dir, de, bh, offset)) | ||
849 | return -1; | 824 | return -1; |
850 | *res_dir = de; | 825 | *res_dir = de; |
851 | return 1; | 826 | return 1; |
@@ -1019,7 +994,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir, const struct q | |||
1019 | int off = (block << EXT4_BLOCK_SIZE_BITS(sb)) | 994 | int off = (block << EXT4_BLOCK_SIZE_BITS(sb)) |
1020 | + ((char *) de - bh->b_data); | 995 | + ((char *) de - bh->b_data); |
1021 | 996 | ||
1022 | if (!ext4_check_dir_entry(__func__, dir, de, bh, off)) { | 997 | if (!ext4_check_dir_entry(dir, de, bh, off)) { |
1023 | brelse(bh); | 998 | brelse(bh); |
1024 | *err = ERR_BAD_DX_DIR; | 999 | *err = ERR_BAD_DX_DIR; |
1025 | goto errout; | 1000 | goto errout; |
@@ -1088,7 +1063,6 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru | |||
1088 | struct dentry *ext4_get_parent(struct dentry *child) | 1063 | struct dentry *ext4_get_parent(struct dentry *child) |
1089 | { | 1064 | { |
1090 | __u32 ino; | 1065 | __u32 ino; |
1091 | struct inode *inode; | ||
1092 | static const struct qstr dotdot = { | 1066 | static const struct qstr dotdot = { |
1093 | .name = "..", | 1067 | .name = "..", |
1094 | .len = 2, | 1068 | .len = 2, |
@@ -1097,7 +1071,6 @@ struct dentry *ext4_get_parent(struct dentry *child) | |||
1097 | struct buffer_head *bh; | 1071 | struct buffer_head *bh; |
1098 | 1072 | ||
1099 | bh = ext4_find_entry(child->d_inode, &dotdot, &de); | 1073 | bh = ext4_find_entry(child->d_inode, &dotdot, &de); |
1100 | inode = NULL; | ||
1101 | if (!bh) | 1074 | if (!bh) |
1102 | return ERR_PTR(-ENOENT); | 1075 | return ERR_PTR(-ENOENT); |
1103 | ino = le32_to_cpu(de->inode); | 1076 | ino = le32_to_cpu(de->inode); |
@@ -1305,8 +1278,7 @@ static int add_dirent_to_buf(handle_t *handle, struct dentry *dentry, | |||
1305 | de = (struct ext4_dir_entry_2 *)bh->b_data; | 1278 | de = (struct ext4_dir_entry_2 *)bh->b_data; |
1306 | top = bh->b_data + blocksize - reclen; | 1279 | top = bh->b_data + blocksize - reclen; |
1307 | while ((char *) de <= top) { | 1280 | while ((char *) de <= top) { |
1308 | if (!ext4_check_dir_entry("ext4_add_entry", dir, de, | 1281 | if (!ext4_check_dir_entry(dir, de, bh, offset)) |
1309 | bh, offset)) | ||
1310 | return -EIO; | 1282 | return -EIO; |
1311 | if (ext4_match(namelen, name, de)) | 1283 | if (ext4_match(namelen, name, de)) |
1312 | return -EEXIST; | 1284 | return -EEXIST; |
@@ -1673,7 +1645,7 @@ static int ext4_delete_entry(handle_t *handle, | |||
1673 | pde = NULL; | 1645 | pde = NULL; |
1674 | de = (struct ext4_dir_entry_2 *) bh->b_data; | 1646 | de = (struct ext4_dir_entry_2 *) bh->b_data; |
1675 | while (i < bh->b_size) { | 1647 | while (i < bh->b_size) { |
1676 | if (!ext4_check_dir_entry("ext4_delete_entry", dir, de, bh, i)) | 1648 | if (!ext4_check_dir_entry(dir, de, bh, i)) |
1677 | return -EIO; | 1649 | return -EIO; |
1678 | if (de == de_del) { | 1650 | if (de == de_del) { |
1679 | BUFFER_TRACE(bh, "get_write_access"); | 1651 | BUFFER_TRACE(bh, "get_write_access"); |
@@ -1956,7 +1928,7 @@ static int empty_dir(struct inode *inode) | |||
1956 | } | 1928 | } |
1957 | de = (struct ext4_dir_entry_2 *) bh->b_data; | 1929 | de = (struct ext4_dir_entry_2 *) bh->b_data; |
1958 | } | 1930 | } |
1959 | if (!ext4_check_dir_entry("empty_dir", inode, de, bh, offset)) { | 1931 | if (!ext4_check_dir_entry(inode, de, bh, offset)) { |
1960 | de = (struct ext4_dir_entry_2 *)(bh->b_data + | 1932 | de = (struct ext4_dir_entry_2 *)(bh->b_data + |
1961 | sb->s_blocksize); | 1933 | sb->s_blocksize); |
1962 | offset = (offset | (sb->s_blocksize - 1)) + 1; | 1934 | offset = (offset | (sb->s_blocksize - 1)) + 1; |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 6df797eb9aeb..ca5c8aa00a2f 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
@@ -921,8 +921,7 @@ int ext4_group_add(struct super_block *sb, struct ext4_new_group_data *input) | |||
921 | &sbi->s_flex_groups[flex_group].free_inodes); | 921 | &sbi->s_flex_groups[flex_group].free_inodes); |
922 | } | 922 | } |
923 | 923 | ||
924 | ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh); | 924 | ext4_handle_dirty_super(handle, sb); |
925 | sb->s_dirt = 1; | ||
926 | 925 | ||
927 | exit_journal: | 926 | exit_journal: |
928 | mutex_unlock(&sbi->s_resize_lock); | 927 | mutex_unlock(&sbi->s_resize_lock); |
@@ -953,7 +952,6 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
953 | ext4_fsblk_t n_blocks_count) | 952 | ext4_fsblk_t n_blocks_count) |
954 | { | 953 | { |
955 | ext4_fsblk_t o_blocks_count; | 954 | ext4_fsblk_t o_blocks_count; |
956 | ext4_group_t o_groups_count; | ||
957 | ext4_grpblk_t last; | 955 | ext4_grpblk_t last; |
958 | ext4_grpblk_t add; | 956 | ext4_grpblk_t add; |
959 | struct buffer_head *bh; | 957 | struct buffer_head *bh; |
@@ -965,7 +963,6 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
965 | * yet: we're going to revalidate es->s_blocks_count after | 963 | * yet: we're going to revalidate es->s_blocks_count after |
966 | * taking the s_resize_lock below. */ | 964 | * taking the s_resize_lock below. */ |
967 | o_blocks_count = ext4_blocks_count(es); | 965 | o_blocks_count = ext4_blocks_count(es); |
968 | o_groups_count = EXT4_SB(sb)->s_groups_count; | ||
969 | 966 | ||
970 | if (test_opt(sb, DEBUG)) | 967 | if (test_opt(sb, DEBUG)) |
971 | printk(KERN_DEBUG "EXT4-fs: extending last group from %llu uto %llu blocks\n", | 968 | printk(KERN_DEBUG "EXT4-fs: extending last group from %llu uto %llu blocks\n", |
@@ -1045,13 +1042,12 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, | |||
1045 | goto exit_put; | 1042 | goto exit_put; |
1046 | } | 1043 | } |
1047 | ext4_blocks_count_set(es, o_blocks_count + add); | 1044 | ext4_blocks_count_set(es, o_blocks_count + add); |
1048 | ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh); | ||
1049 | sb->s_dirt = 1; | ||
1050 | mutex_unlock(&EXT4_SB(sb)->s_resize_lock); | 1045 | mutex_unlock(&EXT4_SB(sb)->s_resize_lock); |
1051 | ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count, | 1046 | ext4_debug("freeing blocks %llu through %llu\n", o_blocks_count, |
1052 | o_blocks_count + add); | 1047 | o_blocks_count + add); |
1053 | /* We add the blocks to the bitmap and set the group need init bit */ | 1048 | /* We add the blocks to the bitmap and set the group need init bit */ |
1054 | ext4_add_groupblocks(handle, sb, o_blocks_count, add); | 1049 | ext4_add_groupblocks(handle, sb, o_blocks_count, add); |
1050 | ext4_handle_dirty_super(handle, sb); | ||
1055 | ext4_debug("freed blocks %llu through %llu\n", o_blocks_count, | 1051 | ext4_debug("freed blocks %llu through %llu\n", o_blocks_count, |
1056 | o_blocks_count + add); | 1052 | o_blocks_count + add); |
1057 | if ((err = ext4_journal_stop(handle))) | 1053 | if ((err = ext4_journal_stop(handle))) |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 4e8983a9811b..8d65575f8c8c 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -241,14 +241,14 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) | |||
241 | if (sb->s_flags & MS_RDONLY) | 241 | if (sb->s_flags & MS_RDONLY) |
242 | return ERR_PTR(-EROFS); | 242 | return ERR_PTR(-EROFS); |
243 | 243 | ||
244 | vfs_check_frozen(sb, SB_FREEZE_WRITE); | 244 | vfs_check_frozen(sb, SB_FREEZE_TRANS); |
245 | /* Special case here: if the journal has aborted behind our | 245 | /* Special case here: if the journal has aborted behind our |
246 | * backs (eg. EIO in the commit thread), then we still need to | 246 | * backs (eg. EIO in the commit thread), then we still need to |
247 | * take the FS itself readonly cleanly. */ | 247 | * take the FS itself readonly cleanly. */ |
248 | journal = EXT4_SB(sb)->s_journal; | 248 | journal = EXT4_SB(sb)->s_journal; |
249 | if (journal) { | 249 | if (journal) { |
250 | if (is_journal_aborted(journal)) { | 250 | if (is_journal_aborted(journal)) { |
251 | ext4_abort(sb, __func__, "Detected aborted journal"); | 251 | ext4_abort(sb, "Detected aborted journal"); |
252 | return ERR_PTR(-EROFS); | 252 | return ERR_PTR(-EROFS); |
253 | } | 253 | } |
254 | return jbd2_journal_start(journal, nblocks); | 254 | return jbd2_journal_start(journal, nblocks); |
@@ -262,7 +262,7 @@ handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks) | |||
262 | * that sync() will call the filesystem's write_super callback if | 262 | * that sync() will call the filesystem's write_super callback if |
263 | * appropriate. | 263 | * appropriate. |
264 | */ | 264 | */ |
265 | int __ext4_journal_stop(const char *where, handle_t *handle) | 265 | int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle) |
266 | { | 266 | { |
267 | struct super_block *sb; | 267 | struct super_block *sb; |
268 | int err; | 268 | int err; |
@@ -279,12 +279,13 @@ int __ext4_journal_stop(const char *where, handle_t *handle) | |||
279 | if (!err) | 279 | if (!err) |
280 | err = rc; | 280 | err = rc; |
281 | if (err) | 281 | if (err) |
282 | __ext4_std_error(sb, where, err); | 282 | __ext4_std_error(sb, where, line, err); |
283 | return err; | 283 | return err; |
284 | } | 284 | } |
285 | 285 | ||
286 | void ext4_journal_abort_handle(const char *caller, const char *err_fn, | 286 | void ext4_journal_abort_handle(const char *caller, unsigned int line, |
287 | struct buffer_head *bh, handle_t *handle, int err) | 287 | const char *err_fn, struct buffer_head *bh, |
288 | handle_t *handle, int err) | ||
288 | { | 289 | { |
289 | char nbuf[16]; | 290 | char nbuf[16]; |
290 | const char *errstr = ext4_decode_error(NULL, err, nbuf); | 291 | const char *errstr = ext4_decode_error(NULL, err, nbuf); |
@@ -300,12 +301,47 @@ void ext4_journal_abort_handle(const char *caller, const char *err_fn, | |||
300 | if (is_handle_aborted(handle)) | 301 | if (is_handle_aborted(handle)) |
301 | return; | 302 | return; |
302 | 303 | ||
303 | printk(KERN_ERR "%s: aborting transaction: %s in %s\n", | 304 | printk(KERN_ERR "%s:%d: aborting transaction: %s in %s\n", |
304 | caller, errstr, err_fn); | 305 | caller, line, errstr, err_fn); |
305 | 306 | ||
306 | jbd2_journal_abort_handle(handle); | 307 | jbd2_journal_abort_handle(handle); |
307 | } | 308 | } |
308 | 309 | ||
310 | static void __save_error_info(struct super_block *sb, const char *func, | ||
311 | unsigned int line) | ||
312 | { | ||
313 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | ||
314 | |||
315 | EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; | ||
316 | es->s_state |= cpu_to_le16(EXT4_ERROR_FS); | ||
317 | es->s_last_error_time = cpu_to_le32(get_seconds()); | ||
318 | strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func)); | ||
319 | es->s_last_error_line = cpu_to_le32(line); | ||
320 | if (!es->s_first_error_time) { | ||
321 | es->s_first_error_time = es->s_last_error_time; | ||
322 | strncpy(es->s_first_error_func, func, | ||
323 | sizeof(es->s_first_error_func)); | ||
324 | es->s_first_error_line = cpu_to_le32(line); | ||
325 | es->s_first_error_ino = es->s_last_error_ino; | ||
326 | es->s_first_error_block = es->s_last_error_block; | ||
327 | } | ||
328 | /* | ||
329 | * Start the daily error reporting function if it hasn't been | ||
330 | * started already | ||
331 | */ | ||
332 | if (!es->s_error_count) | ||
333 | mod_timer(&EXT4_SB(sb)->s_err_report, jiffies + 24*60*60*HZ); | ||
334 | es->s_error_count = cpu_to_le32(le32_to_cpu(es->s_error_count) + 1); | ||
335 | } | ||
336 | |||
337 | static void save_error_info(struct super_block *sb, const char *func, | ||
338 | unsigned int line) | ||
339 | { | ||
340 | __save_error_info(sb, func, line); | ||
341 | ext4_commit_super(sb, 1); | ||
342 | } | ||
343 | |||
344 | |||
309 | /* Deal with the reporting of failure conditions on a filesystem such as | 345 | /* Deal with the reporting of failure conditions on a filesystem such as |
310 | * inconsistencies detected or read IO failures. | 346 | * inconsistencies detected or read IO failures. |
311 | * | 347 | * |
@@ -323,11 +359,6 @@ void ext4_journal_abort_handle(const char *caller, const char *err_fn, | |||
323 | 359 | ||
324 | static void ext4_handle_error(struct super_block *sb) | 360 | static void ext4_handle_error(struct super_block *sb) |
325 | { | 361 | { |
326 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | ||
327 | |||
328 | EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; | ||
329 | es->s_state |= cpu_to_le16(EXT4_ERROR_FS); | ||
330 | |||
331 | if (sb->s_flags & MS_RDONLY) | 362 | if (sb->s_flags & MS_RDONLY) |
332 | return; | 363 | return; |
333 | 364 | ||
@@ -342,19 +373,19 @@ static void ext4_handle_error(struct super_block *sb) | |||
342 | ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); | 373 | ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); |
343 | sb->s_flags |= MS_RDONLY; | 374 | sb->s_flags |= MS_RDONLY; |
344 | } | 375 | } |
345 | ext4_commit_super(sb, 1); | ||
346 | if (test_opt(sb, ERRORS_PANIC)) | 376 | if (test_opt(sb, ERRORS_PANIC)) |
347 | panic("EXT4-fs (device %s): panic forced after error\n", | 377 | panic("EXT4-fs (device %s): panic forced after error\n", |
348 | sb->s_id); | 378 | sb->s_id); |
349 | } | 379 | } |
350 | 380 | ||
351 | void __ext4_error(struct super_block *sb, const char *function, | 381 | void __ext4_error(struct super_block *sb, const char *function, |
352 | const char *fmt, ...) | 382 | unsigned int line, const char *fmt, ...) |
353 | { | 383 | { |
354 | va_list args; | 384 | va_list args; |
355 | 385 | ||
356 | va_start(args, fmt); | 386 | va_start(args, fmt); |
357 | printk(KERN_CRIT "EXT4-fs error (device %s): %s: ", sb->s_id, function); | 387 | printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: comm %s: ", |
388 | sb->s_id, function, line, current->comm); | ||
358 | vprintk(fmt, args); | 389 | vprintk(fmt, args); |
359 | printk("\n"); | 390 | printk("\n"); |
360 | va_end(args); | 391 | va_end(args); |
@@ -362,14 +393,22 @@ void __ext4_error(struct super_block *sb, const char *function, | |||
362 | ext4_handle_error(sb); | 393 | ext4_handle_error(sb); |
363 | } | 394 | } |
364 | 395 | ||
365 | void ext4_error_inode(const char *function, struct inode *inode, | 396 | void ext4_error_inode(struct inode *inode, const char *function, |
397 | unsigned int line, ext4_fsblk_t block, | ||
366 | const char *fmt, ...) | 398 | const char *fmt, ...) |
367 | { | 399 | { |
368 | va_list args; | 400 | va_list args; |
401 | struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; | ||
369 | 402 | ||
403 | es->s_last_error_ino = cpu_to_le32(inode->i_ino); | ||
404 | es->s_last_error_block = cpu_to_le64(block); | ||
405 | save_error_info(inode->i_sb, function, line); | ||
370 | va_start(args, fmt); | 406 | va_start(args, fmt); |
371 | printk(KERN_CRIT "EXT4-fs error (device %s): %s: inode #%lu: (comm %s) ", | 407 | printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: inode #%lu: ", |
372 | inode->i_sb->s_id, function, inode->i_ino, current->comm); | 408 | inode->i_sb->s_id, function, line, inode->i_ino); |
409 | if (block) | ||
410 | printk("block %llu: ", block); | ||
411 | printk("comm %s: ", current->comm); | ||
373 | vprintk(fmt, args); | 412 | vprintk(fmt, args); |
374 | printk("\n"); | 413 | printk("\n"); |
375 | va_end(args); | 414 | va_end(args); |
@@ -377,20 +416,26 @@ void ext4_error_inode(const char *function, struct inode *inode, | |||
377 | ext4_handle_error(inode->i_sb); | 416 | ext4_handle_error(inode->i_sb); |
378 | } | 417 | } |
379 | 418 | ||
380 | void ext4_error_file(const char *function, struct file *file, | 419 | void ext4_error_file(struct file *file, const char *function, |
381 | const char *fmt, ...) | 420 | unsigned int line, const char *fmt, ...) |
382 | { | 421 | { |
383 | va_list args; | 422 | va_list args; |
423 | struct ext4_super_block *es; | ||
384 | struct inode *inode = file->f_dentry->d_inode; | 424 | struct inode *inode = file->f_dentry->d_inode; |
385 | char pathname[80], *path; | 425 | char pathname[80], *path; |
386 | 426 | ||
427 | es = EXT4_SB(inode->i_sb)->s_es; | ||
428 | es->s_last_error_ino = cpu_to_le32(inode->i_ino); | ||
429 | save_error_info(inode->i_sb, function, line); | ||
387 | va_start(args, fmt); | 430 | va_start(args, fmt); |
388 | path = d_path(&(file->f_path), pathname, sizeof(pathname)); | 431 | path = d_path(&(file->f_path), pathname, sizeof(pathname)); |
389 | if (!path) | 432 | if (!path) |
390 | path = "(unknown)"; | 433 | path = "(unknown)"; |
391 | printk(KERN_CRIT | 434 | printk(KERN_CRIT |
392 | "EXT4-fs error (device %s): %s: inode #%lu (comm %s path %s): ", | 435 | "EXT4-fs error (device %s): %s:%d: inode #%lu " |
393 | inode->i_sb->s_id, function, inode->i_ino, current->comm, path); | 436 | "(comm %s path %s): ", |
437 | inode->i_sb->s_id, function, line, inode->i_ino, | ||
438 | current->comm, path); | ||
394 | vprintk(fmt, args); | 439 | vprintk(fmt, args); |
395 | printk("\n"); | 440 | printk("\n"); |
396 | va_end(args); | 441 | va_end(args); |
@@ -435,7 +480,8 @@ static const char *ext4_decode_error(struct super_block *sb, int errno, | |||
435 | /* __ext4_std_error decodes expected errors from journaling functions | 480 | /* __ext4_std_error decodes expected errors from journaling functions |
436 | * automatically and invokes the appropriate error response. */ | 481 | * automatically and invokes the appropriate error response. */ |
437 | 482 | ||
438 | void __ext4_std_error(struct super_block *sb, const char *function, int errno) | 483 | void __ext4_std_error(struct super_block *sb, const char *function, |
484 | unsigned int line, int errno) | ||
439 | { | 485 | { |
440 | char nbuf[16]; | 486 | char nbuf[16]; |
441 | const char *errstr; | 487 | const char *errstr; |
@@ -448,8 +494,9 @@ void __ext4_std_error(struct super_block *sb, const char *function, int errno) | |||
448 | return; | 494 | return; |
449 | 495 | ||
450 | errstr = ext4_decode_error(sb, errno, nbuf); | 496 | errstr = ext4_decode_error(sb, errno, nbuf); |
451 | printk(KERN_CRIT "EXT4-fs error (device %s) in %s: %s\n", | 497 | printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n", |
452 | sb->s_id, function, errstr); | 498 | sb->s_id, function, line, errstr); |
499 | save_error_info(sb, function, line); | ||
453 | 500 | ||
454 | ext4_handle_error(sb); | 501 | ext4_handle_error(sb); |
455 | } | 502 | } |
@@ -464,29 +511,29 @@ void __ext4_std_error(struct super_block *sb, const char *function, int errno) | |||
464 | * case we take the easy way out and panic immediately. | 511 | * case we take the easy way out and panic immediately. |
465 | */ | 512 | */ |
466 | 513 | ||
467 | void ext4_abort(struct super_block *sb, const char *function, | 514 | void __ext4_abort(struct super_block *sb, const char *function, |
468 | const char *fmt, ...) | 515 | unsigned int line, const char *fmt, ...) |
469 | { | 516 | { |
470 | va_list args; | 517 | va_list args; |
471 | 518 | ||
519 | save_error_info(sb, function, line); | ||
472 | va_start(args, fmt); | 520 | va_start(args, fmt); |
473 | printk(KERN_CRIT "EXT4-fs error (device %s): %s: ", sb->s_id, function); | 521 | printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: ", sb->s_id, |
522 | function, line); | ||
474 | vprintk(fmt, args); | 523 | vprintk(fmt, args); |
475 | printk("\n"); | 524 | printk("\n"); |
476 | va_end(args); | 525 | va_end(args); |
477 | 526 | ||
527 | if ((sb->s_flags & MS_RDONLY) == 0) { | ||
528 | ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); | ||
529 | sb->s_flags |= MS_RDONLY; | ||
530 | EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; | ||
531 | if (EXT4_SB(sb)->s_journal) | ||
532 | jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); | ||
533 | save_error_info(sb, function, line); | ||
534 | } | ||
478 | if (test_opt(sb, ERRORS_PANIC)) | 535 | if (test_opt(sb, ERRORS_PANIC)) |
479 | panic("EXT4-fs panic from previous error\n"); | 536 | panic("EXT4-fs panic from previous error\n"); |
480 | |||
481 | if (sb->s_flags & MS_RDONLY) | ||
482 | return; | ||
483 | |||
484 | ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only"); | ||
485 | EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; | ||
486 | sb->s_flags |= MS_RDONLY; | ||
487 | EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; | ||
488 | if (EXT4_SB(sb)->s_journal) | ||
489 | jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); | ||
490 | } | 537 | } |
491 | 538 | ||
492 | void ext4_msg (struct super_block * sb, const char *prefix, | 539 | void ext4_msg (struct super_block * sb, const char *prefix, |
@@ -502,38 +549,47 @@ void ext4_msg (struct super_block * sb, const char *prefix, | |||
502 | } | 549 | } |
503 | 550 | ||
504 | void __ext4_warning(struct super_block *sb, const char *function, | 551 | void __ext4_warning(struct super_block *sb, const char *function, |
505 | const char *fmt, ...) | 552 | unsigned int line, const char *fmt, ...) |
506 | { | 553 | { |
507 | va_list args; | 554 | va_list args; |
508 | 555 | ||
509 | va_start(args, fmt); | 556 | va_start(args, fmt); |
510 | printk(KERN_WARNING "EXT4-fs warning (device %s): %s: ", | 557 | printk(KERN_WARNING "EXT4-fs warning (device %s): %s:%d: ", |
511 | sb->s_id, function); | 558 | sb->s_id, function, line); |
512 | vprintk(fmt, args); | 559 | vprintk(fmt, args); |
513 | printk("\n"); | 560 | printk("\n"); |
514 | va_end(args); | 561 | va_end(args); |
515 | } | 562 | } |
516 | 563 | ||
517 | void ext4_grp_locked_error(struct super_block *sb, ext4_group_t grp, | 564 | void __ext4_grp_locked_error(const char *function, unsigned int line, |
518 | const char *function, const char *fmt, ...) | 565 | struct super_block *sb, ext4_group_t grp, |
566 | unsigned long ino, ext4_fsblk_t block, | ||
567 | const char *fmt, ...) | ||
519 | __releases(bitlock) | 568 | __releases(bitlock) |
520 | __acquires(bitlock) | 569 | __acquires(bitlock) |
521 | { | 570 | { |
522 | va_list args; | 571 | va_list args; |
523 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | 572 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; |
524 | 573 | ||
574 | es->s_last_error_ino = cpu_to_le32(ino); | ||
575 | es->s_last_error_block = cpu_to_le64(block); | ||
576 | __save_error_info(sb, function, line); | ||
525 | va_start(args, fmt); | 577 | va_start(args, fmt); |
526 | printk(KERN_CRIT "EXT4-fs error (device %s): %s: ", sb->s_id, function); | 578 | printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u", |
579 | sb->s_id, function, line, grp); | ||
580 | if (ino) | ||
581 | printk("inode %lu: ", ino); | ||
582 | if (block) | ||
583 | printk("block %llu:", (unsigned long long) block); | ||
527 | vprintk(fmt, args); | 584 | vprintk(fmt, args); |
528 | printk("\n"); | 585 | printk("\n"); |
529 | va_end(args); | 586 | va_end(args); |
530 | 587 | ||
531 | if (test_opt(sb, ERRORS_CONT)) { | 588 | if (test_opt(sb, ERRORS_CONT)) { |
532 | EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; | ||
533 | es->s_state |= cpu_to_le16(EXT4_ERROR_FS); | ||
534 | ext4_commit_super(sb, 0); | 589 | ext4_commit_super(sb, 0); |
535 | return; | 590 | return; |
536 | } | 591 | } |
592 | |||
537 | ext4_unlock_group(sb, grp); | 593 | ext4_unlock_group(sb, grp); |
538 | ext4_handle_error(sb); | 594 | ext4_handle_error(sb); |
539 | /* | 595 | /* |
@@ -660,8 +716,7 @@ static void ext4_put_super(struct super_block *sb) | |||
660 | err = jbd2_journal_destroy(sbi->s_journal); | 716 | err = jbd2_journal_destroy(sbi->s_journal); |
661 | sbi->s_journal = NULL; | 717 | sbi->s_journal = NULL; |
662 | if (err < 0) | 718 | if (err < 0) |
663 | ext4_abort(sb, __func__, | 719 | ext4_abort(sb, "Couldn't clean up the journal"); |
664 | "Couldn't clean up the journal"); | ||
665 | } | 720 | } |
666 | 721 | ||
667 | ext4_release_system_zone(sb); | 722 | ext4_release_system_zone(sb); |
@@ -946,14 +1001,12 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
946 | seq_puts(seq, ",journal_async_commit"); | 1001 | seq_puts(seq, ",journal_async_commit"); |
947 | else if (test_opt(sb, JOURNAL_CHECKSUM)) | 1002 | else if (test_opt(sb, JOURNAL_CHECKSUM)) |
948 | seq_puts(seq, ",journal_checksum"); | 1003 | seq_puts(seq, ",journal_checksum"); |
949 | if (test_opt(sb, NOBH)) | ||
950 | seq_puts(seq, ",nobh"); | ||
951 | if (test_opt(sb, I_VERSION)) | 1004 | if (test_opt(sb, I_VERSION)) |
952 | seq_puts(seq, ",i_version"); | 1005 | seq_puts(seq, ",i_version"); |
953 | if (!test_opt(sb, DELALLOC)) | 1006 | if (!test_opt(sb, DELALLOC) && |
1007 | !(def_mount_opts & EXT4_DEFM_NODELALLOC)) | ||
954 | seq_puts(seq, ",nodelalloc"); | 1008 | seq_puts(seq, ",nodelalloc"); |
955 | 1009 | ||
956 | |||
957 | if (sbi->s_stripe) | 1010 | if (sbi->s_stripe) |
958 | seq_printf(seq, ",stripe=%lu", sbi->s_stripe); | 1011 | seq_printf(seq, ",stripe=%lu", sbi->s_stripe); |
959 | /* | 1012 | /* |
@@ -977,7 +1030,7 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
977 | if (test_opt(sb, NO_AUTO_DA_ALLOC)) | 1030 | if (test_opt(sb, NO_AUTO_DA_ALLOC)) |
978 | seq_puts(seq, ",noauto_da_alloc"); | 1031 | seq_puts(seq, ",noauto_da_alloc"); |
979 | 1032 | ||
980 | if (test_opt(sb, DISCARD)) | 1033 | if (test_opt(sb, DISCARD) && !(def_mount_opts & EXT4_DEFM_DISCARD)) |
981 | seq_puts(seq, ",discard"); | 1034 | seq_puts(seq, ",discard"); |
982 | 1035 | ||
983 | if (test_opt(sb, NOLOAD)) | 1036 | if (test_opt(sb, NOLOAD)) |
@@ -986,6 +1039,10 @@ static int ext4_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
986 | if (test_opt(sb, DIOREAD_NOLOCK)) | 1039 | if (test_opt(sb, DIOREAD_NOLOCK)) |
987 | seq_puts(seq, ",dioread_nolock"); | 1040 | seq_puts(seq, ",dioread_nolock"); |
988 | 1041 | ||
1042 | if (test_opt(sb, BLOCK_VALIDITY) && | ||
1043 | !(def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY)) | ||
1044 | seq_puts(seq, ",block_validity"); | ||
1045 | |||
989 | ext4_show_quota_options(seq, sb); | 1046 | ext4_show_quota_options(seq, sb); |
990 | 1047 | ||
991 | return 0; | 1048 | return 0; |
@@ -1065,6 +1122,7 @@ static int ext4_mark_dquot_dirty(struct dquot *dquot); | |||
1065 | static int ext4_write_info(struct super_block *sb, int type); | 1122 | static int ext4_write_info(struct super_block *sb, int type); |
1066 | static int ext4_quota_on(struct super_block *sb, int type, int format_id, | 1123 | static int ext4_quota_on(struct super_block *sb, int type, int format_id, |
1067 | char *path); | 1124 | char *path); |
1125 | static int ext4_quota_off(struct super_block *sb, int type); | ||
1068 | static int ext4_quota_on_mount(struct super_block *sb, int type); | 1126 | static int ext4_quota_on_mount(struct super_block *sb, int type); |
1069 | static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, | 1127 | static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, |
1070 | size_t len, loff_t off); | 1128 | size_t len, loff_t off); |
@@ -1086,7 +1144,7 @@ static const struct dquot_operations ext4_quota_operations = { | |||
1086 | 1144 | ||
1087 | static const struct quotactl_ops ext4_qctl_operations = { | 1145 | static const struct quotactl_ops ext4_qctl_operations = { |
1088 | .quota_on = ext4_quota_on, | 1146 | .quota_on = ext4_quota_on, |
1089 | .quota_off = dquot_quota_off, | 1147 | .quota_off = ext4_quota_off, |
1090 | .quota_sync = dquot_quota_sync, | 1148 | .quota_sync = dquot_quota_sync, |
1091 | .get_info = dquot_get_dqinfo, | 1149 | .get_info = dquot_get_dqinfo, |
1092 | .set_info = dquot_set_dqinfo, | 1150 | .set_info = dquot_set_dqinfo, |
@@ -1624,10 +1682,12 @@ set_qf_format: | |||
1624 | *n_blocks_count = option; | 1682 | *n_blocks_count = option; |
1625 | break; | 1683 | break; |
1626 | case Opt_nobh: | 1684 | case Opt_nobh: |
1627 | set_opt(sbi->s_mount_opt, NOBH); | 1685 | ext4_msg(sb, KERN_WARNING, |
1686 | "Ignoring deprecated nobh option"); | ||
1628 | break; | 1687 | break; |
1629 | case Opt_bh: | 1688 | case Opt_bh: |
1630 | clear_opt(sbi->s_mount_opt, NOBH); | 1689 | ext4_msg(sb, KERN_WARNING, |
1690 | "Ignoring deprecated bh option"); | ||
1631 | break; | 1691 | break; |
1632 | case Opt_i_version: | 1692 | case Opt_i_version: |
1633 | set_opt(sbi->s_mount_opt, I_VERSION); | 1693 | set_opt(sbi->s_mount_opt, I_VERSION); |
@@ -2249,6 +2309,8 @@ static ssize_t session_write_kbytes_show(struct ext4_attr *a, | |||
2249 | { | 2309 | { |
2250 | struct super_block *sb = sbi->s_buddy_cache->i_sb; | 2310 | struct super_block *sb = sbi->s_buddy_cache->i_sb; |
2251 | 2311 | ||
2312 | if (!sb->s_bdev->bd_part) | ||
2313 | return snprintf(buf, PAGE_SIZE, "0\n"); | ||
2252 | return snprintf(buf, PAGE_SIZE, "%lu\n", | 2314 | return snprintf(buf, PAGE_SIZE, "%lu\n", |
2253 | (part_stat_read(sb->s_bdev->bd_part, sectors[1]) - | 2315 | (part_stat_read(sb->s_bdev->bd_part, sectors[1]) - |
2254 | sbi->s_sectors_written_start) >> 1); | 2316 | sbi->s_sectors_written_start) >> 1); |
@@ -2259,6 +2321,8 @@ static ssize_t lifetime_write_kbytes_show(struct ext4_attr *a, | |||
2259 | { | 2321 | { |
2260 | struct super_block *sb = sbi->s_buddy_cache->i_sb; | 2322 | struct super_block *sb = sbi->s_buddy_cache->i_sb; |
2261 | 2323 | ||
2324 | if (!sb->s_bdev->bd_part) | ||
2325 | return snprintf(buf, PAGE_SIZE, "0\n"); | ||
2262 | return snprintf(buf, PAGE_SIZE, "%llu\n", | 2326 | return snprintf(buf, PAGE_SIZE, "%llu\n", |
2263 | (unsigned long long)(sbi->s_kbytes_written + | 2327 | (unsigned long long)(sbi->s_kbytes_written + |
2264 | ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - | 2328 | ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - |
@@ -2431,6 +2495,53 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly) | |||
2431 | return 1; | 2495 | return 1; |
2432 | } | 2496 | } |
2433 | 2497 | ||
2498 | /* | ||
2499 | * This function is called once a day if we have errors logged | ||
2500 | * on the file system | ||
2501 | */ | ||
2502 | static void print_daily_error_info(unsigned long arg) | ||
2503 | { | ||
2504 | struct super_block *sb = (struct super_block *) arg; | ||
2505 | struct ext4_sb_info *sbi; | ||
2506 | struct ext4_super_block *es; | ||
2507 | |||
2508 | sbi = EXT4_SB(sb); | ||
2509 | es = sbi->s_es; | ||
2510 | |||
2511 | if (es->s_error_count) | ||
2512 | ext4_msg(sb, KERN_NOTICE, "error count: %u", | ||
2513 | le32_to_cpu(es->s_error_count)); | ||
2514 | if (es->s_first_error_time) { | ||
2515 | printk(KERN_NOTICE "EXT4-fs (%s): initial error at %u: %.*s:%d", | ||
2516 | sb->s_id, le32_to_cpu(es->s_first_error_time), | ||
2517 | (int) sizeof(es->s_first_error_func), | ||
2518 | es->s_first_error_func, | ||
2519 | le32_to_cpu(es->s_first_error_line)); | ||
2520 | if (es->s_first_error_ino) | ||
2521 | printk(": inode %u", | ||
2522 | le32_to_cpu(es->s_first_error_ino)); | ||
2523 | if (es->s_first_error_block) | ||
2524 | printk(": block %llu", (unsigned long long) | ||
2525 | le64_to_cpu(es->s_first_error_block)); | ||
2526 | printk("\n"); | ||
2527 | } | ||
2528 | if (es->s_last_error_time) { | ||
2529 | printk(KERN_NOTICE "EXT4-fs (%s): last error at %u: %.*s:%d", | ||
2530 | sb->s_id, le32_to_cpu(es->s_last_error_time), | ||
2531 | (int) sizeof(es->s_last_error_func), | ||
2532 | es->s_last_error_func, | ||
2533 | le32_to_cpu(es->s_last_error_line)); | ||
2534 | if (es->s_last_error_ino) | ||
2535 | printk(": inode %u", | ||
2536 | le32_to_cpu(es->s_last_error_ino)); | ||
2537 | if (es->s_last_error_block) | ||
2538 | printk(": block %llu", (unsigned long long) | ||
2539 | le64_to_cpu(es->s_last_error_block)); | ||
2540 | printk("\n"); | ||
2541 | } | ||
2542 | mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */ | ||
2543 | } | ||
2544 | |||
2434 | static int ext4_fill_super(struct super_block *sb, void *data, int silent) | 2545 | static int ext4_fill_super(struct super_block *sb, void *data, int silent) |
2435 | __releases(kernel_lock) | 2546 | __releases(kernel_lock) |
2436 | __acquires(kernel_lock) | 2547 | __acquires(kernel_lock) |
@@ -2448,7 +2559,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2448 | struct inode *root; | 2559 | struct inode *root; |
2449 | char *cp; | 2560 | char *cp; |
2450 | const char *descr; | 2561 | const char *descr; |
2451 | int ret = -EINVAL; | 2562 | int ret = -ENOMEM; |
2452 | int blocksize; | 2563 | int blocksize; |
2453 | unsigned int db_count; | 2564 | unsigned int db_count; |
2454 | unsigned int i; | 2565 | unsigned int i; |
@@ -2459,13 +2570,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2459 | 2570 | ||
2460 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); | 2571 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
2461 | if (!sbi) | 2572 | if (!sbi) |
2462 | return -ENOMEM; | 2573 | goto out_free_orig; |
2463 | 2574 | ||
2464 | sbi->s_blockgroup_lock = | 2575 | sbi->s_blockgroup_lock = |
2465 | kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL); | 2576 | kzalloc(sizeof(struct blockgroup_lock), GFP_KERNEL); |
2466 | if (!sbi->s_blockgroup_lock) { | 2577 | if (!sbi->s_blockgroup_lock) { |
2467 | kfree(sbi); | 2578 | kfree(sbi); |
2468 | return -ENOMEM; | 2579 | goto out_free_orig; |
2469 | } | 2580 | } |
2470 | sb->s_fs_info = sbi; | 2581 | sb->s_fs_info = sbi; |
2471 | sbi->s_mount_opt = 0; | 2582 | sbi->s_mount_opt = 0; |
@@ -2473,8 +2584,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2473 | sbi->s_resgid = EXT4_DEF_RESGID; | 2584 | sbi->s_resgid = EXT4_DEF_RESGID; |
2474 | sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS; | 2585 | sbi->s_inode_readahead_blks = EXT4_DEF_INODE_READAHEAD_BLKS; |
2475 | sbi->s_sb_block = sb_block; | 2586 | sbi->s_sb_block = sb_block; |
2476 | sbi->s_sectors_written_start = part_stat_read(sb->s_bdev->bd_part, | 2587 | if (sb->s_bdev->bd_part) |
2477 | sectors[1]); | 2588 | sbi->s_sectors_written_start = |
2589 | part_stat_read(sb->s_bdev->bd_part, sectors[1]); | ||
2478 | 2590 | ||
2479 | unlock_kernel(); | 2591 | unlock_kernel(); |
2480 | 2592 | ||
@@ -2482,6 +2594,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2482 | for (cp = sb->s_id; (cp = strchr(cp, '/'));) | 2594 | for (cp = sb->s_id; (cp = strchr(cp, '/'));) |
2483 | *cp = '!'; | 2595 | *cp = '!'; |
2484 | 2596 | ||
2597 | ret = -EINVAL; | ||
2485 | blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE); | 2598 | blocksize = sb_min_blocksize(sb, EXT4_MIN_BLOCK_SIZE); |
2486 | if (!blocksize) { | 2599 | if (!blocksize) { |
2487 | ext4_msg(sb, KERN_ERR, "unable to set blocksize"); | 2600 | ext4_msg(sb, KERN_ERR, "unable to set blocksize"); |
@@ -2546,6 +2659,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2546 | set_opt(sbi->s_mount_opt, ERRORS_CONT); | 2659 | set_opt(sbi->s_mount_opt, ERRORS_CONT); |
2547 | else | 2660 | else |
2548 | set_opt(sbi->s_mount_opt, ERRORS_RO); | 2661 | set_opt(sbi->s_mount_opt, ERRORS_RO); |
2662 | if (def_mount_opts & EXT4_DEFM_BLOCK_VALIDITY) | ||
2663 | set_opt(sbi->s_mount_opt, BLOCK_VALIDITY); | ||
2664 | if (def_mount_opts & EXT4_DEFM_DISCARD) | ||
2665 | set_opt(sbi->s_mount_opt, DISCARD); | ||
2549 | 2666 | ||
2550 | sbi->s_resuid = le16_to_cpu(es->s_def_resuid); | 2667 | sbi->s_resuid = le16_to_cpu(es->s_def_resuid); |
2551 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); | 2668 | sbi->s_resgid = le16_to_cpu(es->s_def_resgid); |
@@ -2553,15 +2670,23 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
2553 | sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME; | 2670 | sbi->s_min_batch_time = EXT4_DEF_MIN_BATCH_TIME; |
2554 | sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME; | 2671 | sbi->s_max_batch_time = EXT4_DEF_MAX_BATCH_TIME; |
2555 | 2672 | ||
2556 | set_opt(sbi->s_mount_opt, BARRIER); | 2673 | if ((def_mount_opts & EXT4_DEFM_NOBARRIER) == 0) |
2674 | set_opt(sbi->s_mount_opt, BARRIER); | ||
2557 | 2675 | ||
2558 | /* | 2676 | /* |
2559 | * enable delayed allocation by default | 2677 | * enable delayed allocation by default |
2560 | * Use -o nodelalloc to turn it off | 2678 | * Use -o nodelalloc to turn it off |
2561 | */ | 2679 | */ |
2562 | if (!IS_EXT3_SB(sb)) | 2680 | if (!IS_EXT3_SB(sb) && |
2681 | ((def_mount_opts & EXT4_DEFM_NODELALLOC) == 0)) | ||
2563 | set_opt(sbi->s_mount_opt, DELALLOC); | 2682 | set_opt(sbi->s_mount_opt, DELALLOC); |
2564 | 2683 | ||
2684 | if (!parse_options((char *) sbi->s_es->s_mount_opts, sb, | ||
2685 | &journal_devnum, &journal_ioprio, NULL, 0)) { | ||
2686 | ext4_msg(sb, KERN_WARNING, | ||
2687 | "failed to parse options in superblock: %s", | ||
2688 | sbi->s_es->s_mount_opts); | ||
2689 | } | ||
2565 | if (!parse_options((char *) data, sb, &journal_devnum, | 2690 | if (!parse_options((char *) data, sb, &journal_devnum, |
2566 | &journal_ioprio, NULL, 0)) | 2691 | &journal_ioprio, NULL, 0)) |
2567 | goto failed_mount; | 2692 | goto failed_mount; |
@@ -2912,18 +3037,7 @@ no_journal: | |||
2912 | ext4_msg(sb, KERN_ERR, "insufficient memory"); | 3037 | ext4_msg(sb, KERN_ERR, "insufficient memory"); |
2913 | goto failed_mount_wq; | 3038 | goto failed_mount_wq; |
2914 | } | 3039 | } |
2915 | if (test_opt(sb, NOBH)) { | 3040 | |
2916 | if (!(test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)) { | ||
2917 | ext4_msg(sb, KERN_WARNING, "Ignoring nobh option - " | ||
2918 | "its supported only with writeback mode"); | ||
2919 | clear_opt(sbi->s_mount_opt, NOBH); | ||
2920 | } | ||
2921 | if (test_opt(sb, DIOREAD_NOLOCK)) { | ||
2922 | ext4_msg(sb, KERN_WARNING, "dioread_nolock option is " | ||
2923 | "not supported with nobh mode"); | ||
2924 | goto failed_mount_wq; | ||
2925 | } | ||
2926 | } | ||
2927 | EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten"); | 3041 | EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten"); |
2928 | if (!EXT4_SB(sb)->dio_unwritten_wq) { | 3042 | if (!EXT4_SB(sb)->dio_unwritten_wq) { |
2929 | printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n"); | 3043 | printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n"); |
@@ -3010,7 +3124,7 @@ no_journal: | |||
3010 | ext4_ext_init(sb); | 3124 | ext4_ext_init(sb); |
3011 | err = ext4_mb_init(sb, needs_recovery); | 3125 | err = ext4_mb_init(sb, needs_recovery); |
3012 | if (err) { | 3126 | if (err) { |
3013 | ext4_msg(sb, KERN_ERR, "failed to initalize mballoc (%d)", | 3127 | ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)", |
3014 | err); | 3128 | err); |
3015 | goto failed_mount4; | 3129 | goto failed_mount4; |
3016 | } | 3130 | } |
@@ -3043,7 +3157,14 @@ no_journal: | |||
3043 | descr = "out journal"; | 3157 | descr = "out journal"; |
3044 | 3158 | ||
3045 | ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. " | 3159 | ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. " |
3046 | "Opts: %s", descr, orig_data); | 3160 | "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts, |
3161 | *sbi->s_es->s_mount_opts ? "; " : "", orig_data); | ||
3162 | |||
3163 | init_timer(&sbi->s_err_report); | ||
3164 | sbi->s_err_report.function = print_daily_error_info; | ||
3165 | sbi->s_err_report.data = (unsigned long) sb; | ||
3166 | if (es->s_error_count) | ||
3167 | mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ | ||
3047 | 3168 | ||
3048 | lock_kernel(); | 3169 | lock_kernel(); |
3049 | kfree(orig_data); | 3170 | kfree(orig_data); |
@@ -3093,6 +3214,7 @@ out_fail: | |||
3093 | kfree(sbi->s_blockgroup_lock); | 3214 | kfree(sbi->s_blockgroup_lock); |
3094 | kfree(sbi); | 3215 | kfree(sbi); |
3095 | lock_kernel(); | 3216 | lock_kernel(); |
3217 | out_free_orig: | ||
3096 | kfree(orig_data); | 3218 | kfree(orig_data); |
3097 | return ret; | 3219 | return ret; |
3098 | } | 3220 | } |
@@ -3110,7 +3232,7 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal) | |||
3110 | journal->j_min_batch_time = sbi->s_min_batch_time; | 3232 | journal->j_min_batch_time = sbi->s_min_batch_time; |
3111 | journal->j_max_batch_time = sbi->s_max_batch_time; | 3233 | journal->j_max_batch_time = sbi->s_max_batch_time; |
3112 | 3234 | ||
3113 | spin_lock(&journal->j_state_lock); | 3235 | write_lock(&journal->j_state_lock); |
3114 | if (test_opt(sb, BARRIER)) | 3236 | if (test_opt(sb, BARRIER)) |
3115 | journal->j_flags |= JBD2_BARRIER; | 3237 | journal->j_flags |= JBD2_BARRIER; |
3116 | else | 3238 | else |
@@ -3119,7 +3241,7 @@ static void ext4_init_journal_params(struct super_block *sb, journal_t *journal) | |||
3119 | journal->j_flags |= JBD2_ABORT_ON_SYNCDATA_ERR; | 3241 | journal->j_flags |= JBD2_ABORT_ON_SYNCDATA_ERR; |
3120 | else | 3242 | else |
3121 | journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR; | 3243 | journal->j_flags &= ~JBD2_ABORT_ON_SYNCDATA_ERR; |
3122 | spin_unlock(&journal->j_state_lock); | 3244 | write_unlock(&journal->j_state_lock); |
3123 | } | 3245 | } |
3124 | 3246 | ||
3125 | static journal_t *ext4_get_journal(struct super_block *sb, | 3247 | static journal_t *ext4_get_journal(struct super_block *sb, |
@@ -3327,8 +3449,17 @@ static int ext4_load_journal(struct super_block *sb, | |||
3327 | 3449 | ||
3328 | if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) | 3450 | if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) |
3329 | err = jbd2_journal_wipe(journal, !really_read_only); | 3451 | err = jbd2_journal_wipe(journal, !really_read_only); |
3330 | if (!err) | 3452 | if (!err) { |
3453 | char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL); | ||
3454 | if (save) | ||
3455 | memcpy(save, ((char *) es) + | ||
3456 | EXT4_S_ERR_START, EXT4_S_ERR_LEN); | ||
3331 | err = jbd2_journal_load(journal); | 3457 | err = jbd2_journal_load(journal); |
3458 | if (save) | ||
3459 | memcpy(((char *) es) + EXT4_S_ERR_START, | ||
3460 | save, EXT4_S_ERR_LEN); | ||
3461 | kfree(save); | ||
3462 | } | ||
3332 | 3463 | ||
3333 | if (err) { | 3464 | if (err) { |
3334 | ext4_msg(sb, KERN_ERR, "error loading journal"); | 3465 | ext4_msg(sb, KERN_ERR, "error loading journal"); |
@@ -3384,10 +3515,14 @@ static int ext4_commit_super(struct super_block *sb, int sync) | |||
3384 | */ | 3515 | */ |
3385 | if (!(sb->s_flags & MS_RDONLY)) | 3516 | if (!(sb->s_flags & MS_RDONLY)) |
3386 | es->s_wtime = cpu_to_le32(get_seconds()); | 3517 | es->s_wtime = cpu_to_le32(get_seconds()); |
3387 | es->s_kbytes_written = | 3518 | if (sb->s_bdev->bd_part) |
3388 | cpu_to_le64(EXT4_SB(sb)->s_kbytes_written + | 3519 | es->s_kbytes_written = |
3520 | cpu_to_le64(EXT4_SB(sb)->s_kbytes_written + | ||
3389 | ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - | 3521 | ((part_stat_read(sb->s_bdev->bd_part, sectors[1]) - |
3390 | EXT4_SB(sb)->s_sectors_written_start) >> 1)); | 3522 | EXT4_SB(sb)->s_sectors_written_start) >> 1)); |
3523 | else | ||
3524 | es->s_kbytes_written = | ||
3525 | cpu_to_le64(EXT4_SB(sb)->s_kbytes_written); | ||
3391 | ext4_free_blocks_count_set(es, percpu_counter_sum_positive( | 3526 | ext4_free_blocks_count_set(es, percpu_counter_sum_positive( |
3392 | &EXT4_SB(sb)->s_freeblocks_counter)); | 3527 | &EXT4_SB(sb)->s_freeblocks_counter)); |
3393 | es->s_free_inodes_count = cpu_to_le32(percpu_counter_sum_positive( | 3528 | es->s_free_inodes_count = cpu_to_le32(percpu_counter_sum_positive( |
@@ -3491,7 +3626,7 @@ int ext4_force_commit(struct super_block *sb) | |||
3491 | 3626 | ||
3492 | journal = EXT4_SB(sb)->s_journal; | 3627 | journal = EXT4_SB(sb)->s_journal; |
3493 | if (journal) { | 3628 | if (journal) { |
3494 | vfs_check_frozen(sb, SB_FREEZE_WRITE); | 3629 | vfs_check_frozen(sb, SB_FREEZE_TRANS); |
3495 | ret = ext4_journal_force_commit(journal); | 3630 | ret = ext4_journal_force_commit(journal); |
3496 | } | 3631 | } |
3497 | 3632 | ||
@@ -3616,7 +3751,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) | |||
3616 | } | 3751 | } |
3617 | 3752 | ||
3618 | if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) | 3753 | if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) |
3619 | ext4_abort(sb, __func__, "Abort forced by user"); | 3754 | ext4_abort(sb, "Abort forced by user"); |
3620 | 3755 | ||
3621 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | | 3756 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | |
3622 | (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); | 3757 | (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); |
@@ -3981,6 +4116,18 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, | |||
3981 | return err; | 4116 | return err; |
3982 | } | 4117 | } |
3983 | 4118 | ||
4119 | static int ext4_quota_off(struct super_block *sb, int type) | ||
4120 | { | ||
4121 | /* Force all delayed allocation blocks to be allocated */ | ||
4122 | if (test_opt(sb, DELALLOC)) { | ||
4123 | down_read(&sb->s_umount); | ||
4124 | sync_filesystem(sb); | ||
4125 | up_read(&sb->s_umount); | ||
4126 | } | ||
4127 | |||
4128 | return dquot_quota_off(sb, type); | ||
4129 | } | ||
4130 | |||
3984 | /* Read data from quotafile - avoid pagecache and such because we cannot afford | 4131 | /* Read data from quotafile - avoid pagecache and such because we cannot afford |
3985 | * acquiring the locks... As quota files are never truncated and quota code | 4132 | * acquiring the locks... As quota files are never truncated and quota code |
3986 | * itself serializes the operations (and noone else should touch the files) | 4133 | * itself serializes the operations (and noone else should touch the files) |
@@ -4030,7 +4177,6 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type, | |||
4030 | ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb); | 4177 | ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb); |
4031 | int err = 0; | 4178 | int err = 0; |
4032 | int offset = off & (sb->s_blocksize - 1); | 4179 | int offset = off & (sb->s_blocksize - 1); |
4033 | int journal_quota = EXT4_SB(sb)->s_qf_names[type] != NULL; | ||
4034 | struct buffer_head *bh; | 4180 | struct buffer_head *bh; |
4035 | handle_t *handle = journal_current_handle(); | 4181 | handle_t *handle = journal_current_handle(); |
4036 | 4182 | ||
@@ -4055,24 +4201,16 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type, | |||
4055 | bh = ext4_bread(handle, inode, blk, 1, &err); | 4201 | bh = ext4_bread(handle, inode, blk, 1, &err); |
4056 | if (!bh) | 4202 | if (!bh) |
4057 | goto out; | 4203 | goto out; |
4058 | if (journal_quota) { | 4204 | err = ext4_journal_get_write_access(handle, bh); |
4059 | err = ext4_journal_get_write_access(handle, bh); | 4205 | if (err) { |
4060 | if (err) { | 4206 | brelse(bh); |
4061 | brelse(bh); | 4207 | goto out; |
4062 | goto out; | ||
4063 | } | ||
4064 | } | 4208 | } |
4065 | lock_buffer(bh); | 4209 | lock_buffer(bh); |
4066 | memcpy(bh->b_data+offset, data, len); | 4210 | memcpy(bh->b_data+offset, data, len); |
4067 | flush_dcache_page(bh->b_page); | 4211 | flush_dcache_page(bh->b_page); |
4068 | unlock_buffer(bh); | 4212 | unlock_buffer(bh); |
4069 | if (journal_quota) | 4213 | err = ext4_handle_dirty_metadata(handle, NULL, bh); |
4070 | err = ext4_handle_dirty_metadata(handle, NULL, bh); | ||
4071 | else { | ||
4072 | /* Always do at least ordered writes for quotas */ | ||
4073 | err = ext4_jbd2_file_inode(handle, inode); | ||
4074 | mark_buffer_dirty(bh); | ||
4075 | } | ||
4076 | brelse(bh); | 4214 | brelse(bh); |
4077 | out: | 4215 | out: |
4078 | if (err) { | 4216 | if (err) { |
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 04338009793a..a6f314249574 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c | |||
@@ -458,8 +458,7 @@ static void ext4_xattr_update_super_block(handle_t *handle, | |||
458 | 458 | ||
459 | if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) { | 459 | if (ext4_journal_get_write_access(handle, EXT4_SB(sb)->s_sbh) == 0) { |
460 | EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR); | 460 | EXT4_SET_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_EXT_ATTR); |
461 | sb->s_dirt = 1; | 461 | ext4_handle_dirty_super(handle, sb); |
462 | ext4_handle_dirty_metadata(handle, NULL, EXT4_SB(sb)->s_sbh); | ||
463 | } | 462 | } |
464 | } | 463 | } |
465 | 464 | ||
@@ -178,7 +178,6 @@ static struct fdtable * alloc_fdtable(unsigned int nr) | |||
178 | fdt->open_fds = (fd_set *)data; | 178 | fdt->open_fds = (fd_set *)data; |
179 | data += nr / BITS_PER_BYTE; | 179 | data += nr / BITS_PER_BYTE; |
180 | fdt->close_on_exec = (fd_set *)data; | 180 | fdt->close_on_exec = (fd_set *)data; |
181 | INIT_RCU_HEAD(&fdt->rcu); | ||
182 | fdt->next = NULL; | 181 | fdt->next = NULL; |
183 | 182 | ||
184 | return fdt; | 183 | return fdt; |
@@ -312,7 +311,6 @@ struct files_struct *dup_fd(struct files_struct *oldf, int *errorp) | |||
312 | new_fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init; | 311 | new_fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init; |
313 | new_fdt->open_fds = (fd_set *)&newf->open_fds_init; | 312 | new_fdt->open_fds = (fd_set *)&newf->open_fds_init; |
314 | new_fdt->fd = &newf->fd_array[0]; | 313 | new_fdt->fd = &newf->fd_array[0]; |
315 | INIT_RCU_HEAD(&new_fdt->rcu); | ||
316 | new_fdt->next = NULL; | 314 | new_fdt->next = NULL; |
317 | 315 | ||
318 | spin_lock(&oldf->file_lock); | 316 | spin_lock(&oldf->file_lock); |
@@ -430,7 +428,6 @@ struct files_struct init_files = { | |||
430 | .fd = &init_files.fd_array[0], | 428 | .fd = &init_files.fd_array[0], |
431 | .close_on_exec = (fd_set *)&init_files.close_on_exec_init, | 429 | .close_on_exec = (fd_set *)&init_files.close_on_exec_init, |
432 | .open_fds = (fd_set *)&init_files.open_fds_init, | 430 | .open_fds = (fd_set *)&init_files.open_fds_init, |
433 | .rcu = RCU_HEAD_INIT, | ||
434 | }, | 431 | }, |
435 | .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock), | 432 | .file_lock = __SPIN_LOCK_UNLOCKED(init_task.file_lock), |
436 | }; | 433 | }; |
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index 1e8af939b3e4..5132c99b1ca2 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c | |||
@@ -135,7 +135,7 @@ static int vxfs_remount(struct super_block *sb, int *flags, char *data) | |||
135 | } | 135 | } |
136 | 136 | ||
137 | /** | 137 | /** |
138 | * vxfs_read_super - read superblock into memory and initalize filesystem | 138 | * vxfs_read_super - read superblock into memory and initialize filesystem |
139 | * @sbp: VFS superblock (to fill) | 139 | * @sbp: VFS superblock (to fill) |
140 | * @dp: fs private mount data | 140 | * @dp: fs private mount data |
141 | * @silent: do not complain loudly when sth is wrong | 141 | * @silent: do not complain loudly when sth is wrong |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 0609607d3955..d5be1693ac93 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -38,43 +38,18 @@ int nr_pdflush_threads; | |||
38 | /* | 38 | /* |
39 | * Passed into wb_writeback(), essentially a subset of writeback_control | 39 | * Passed into wb_writeback(), essentially a subset of writeback_control |
40 | */ | 40 | */ |
41 | struct wb_writeback_args { | 41 | struct wb_writeback_work { |
42 | long nr_pages; | 42 | long nr_pages; |
43 | struct super_block *sb; | 43 | struct super_block *sb; |
44 | enum writeback_sync_modes sync_mode; | 44 | enum writeback_sync_modes sync_mode; |
45 | unsigned int for_kupdate:1; | 45 | unsigned int for_kupdate:1; |
46 | unsigned int range_cyclic:1; | 46 | unsigned int range_cyclic:1; |
47 | unsigned int for_background:1; | 47 | unsigned int for_background:1; |
48 | }; | ||
49 | 48 | ||
50 | /* | ||
51 | * Work items for the bdi_writeback threads | ||
52 | */ | ||
53 | struct bdi_work { | ||
54 | struct list_head list; /* pending work list */ | 49 | struct list_head list; /* pending work list */ |
55 | struct rcu_head rcu_head; /* for RCU free/clear of work */ | 50 | struct completion *done; /* set if the caller waits */ |
56 | |||
57 | unsigned long seen; /* threads that have seen this work */ | ||
58 | atomic_t pending; /* number of threads still to do work */ | ||
59 | |||
60 | struct wb_writeback_args args; /* writeback arguments */ | ||
61 | |||
62 | unsigned long state; /* flag bits, see WS_* */ | ||
63 | }; | 51 | }; |
64 | 52 | ||
65 | enum { | ||
66 | WS_INPROGRESS = 0, | ||
67 | WS_ONSTACK, | ||
68 | }; | ||
69 | |||
70 | static inline void bdi_work_init(struct bdi_work *work, | ||
71 | struct wb_writeback_args *args) | ||
72 | { | ||
73 | INIT_RCU_HEAD(&work->rcu_head); | ||
74 | work->args = *args; | ||
75 | __set_bit(WS_INPROGRESS, &work->state); | ||
76 | } | ||
77 | |||
78 | /** | 53 | /** |
79 | * writeback_in_progress - determine whether there is writeback in progress | 54 | * writeback_in_progress - determine whether there is writeback in progress |
80 | * @bdi: the device's backing_dev_info structure. | 55 | * @bdi: the device's backing_dev_info structure. |
@@ -87,49 +62,11 @@ int writeback_in_progress(struct backing_dev_info *bdi) | |||
87 | return !list_empty(&bdi->work_list); | 62 | return !list_empty(&bdi->work_list); |
88 | } | 63 | } |
89 | 64 | ||
90 | static void bdi_work_free(struct rcu_head *head) | 65 | static void bdi_queue_work(struct backing_dev_info *bdi, |
91 | { | 66 | struct wb_writeback_work *work) |
92 | struct bdi_work *work = container_of(head, struct bdi_work, rcu_head); | ||
93 | |||
94 | clear_bit(WS_INPROGRESS, &work->state); | ||
95 | smp_mb__after_clear_bit(); | ||
96 | wake_up_bit(&work->state, WS_INPROGRESS); | ||
97 | |||
98 | if (!test_bit(WS_ONSTACK, &work->state)) | ||
99 | kfree(work); | ||
100 | } | ||
101 | |||
102 | static void wb_clear_pending(struct bdi_writeback *wb, struct bdi_work *work) | ||
103 | { | 67 | { |
104 | /* | ||
105 | * The caller has retrieved the work arguments from this work, | ||
106 | * drop our reference. If this is the last ref, delete and free it | ||
107 | */ | ||
108 | if (atomic_dec_and_test(&work->pending)) { | ||
109 | struct backing_dev_info *bdi = wb->bdi; | ||
110 | |||
111 | spin_lock(&bdi->wb_lock); | ||
112 | list_del_rcu(&work->list); | ||
113 | spin_unlock(&bdi->wb_lock); | ||
114 | |||
115 | call_rcu(&work->rcu_head, bdi_work_free); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | static void bdi_queue_work(struct backing_dev_info *bdi, struct bdi_work *work) | ||
120 | { | ||
121 | work->seen = bdi->wb_mask; | ||
122 | BUG_ON(!work->seen); | ||
123 | atomic_set(&work->pending, bdi->wb_cnt); | ||
124 | BUG_ON(!bdi->wb_cnt); | ||
125 | |||
126 | /* | ||
127 | * list_add_tail_rcu() contains the necessary barriers to | ||
128 | * make sure the above stores are seen before the item is | ||
129 | * noticed on the list | ||
130 | */ | ||
131 | spin_lock(&bdi->wb_lock); | 68 | spin_lock(&bdi->wb_lock); |
132 | list_add_tail_rcu(&work->list, &bdi->work_list); | 69 | list_add_tail(&work->list, &bdi->work_list); |
133 | spin_unlock(&bdi->wb_lock); | 70 | spin_unlock(&bdi->wb_lock); |
134 | 71 | ||
135 | /* | 72 | /* |
@@ -146,55 +83,29 @@ static void bdi_queue_work(struct backing_dev_info *bdi, struct bdi_work *work) | |||
146 | } | 83 | } |
147 | } | 84 | } |
148 | 85 | ||
149 | /* | 86 | static void |
150 | * Used for on-stack allocated work items. The caller needs to wait until | 87 | __bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages, |
151 | * the wb threads have acked the work before it's safe to continue. | 88 | bool range_cyclic, bool for_background) |
152 | */ | ||
153 | static void bdi_wait_on_work_done(struct bdi_work *work) | ||
154 | { | 89 | { |
155 | wait_on_bit(&work->state, WS_INPROGRESS, bdi_sched_wait, | 90 | struct wb_writeback_work *work; |
156 | TASK_UNINTERRUPTIBLE); | ||
157 | } | ||
158 | |||
159 | static void bdi_alloc_queue_work(struct backing_dev_info *bdi, | ||
160 | struct wb_writeback_args *args) | ||
161 | { | ||
162 | struct bdi_work *work; | ||
163 | 91 | ||
164 | /* | 92 | /* |
165 | * This is WB_SYNC_NONE writeback, so if allocation fails just | 93 | * This is WB_SYNC_NONE writeback, so if allocation fails just |
166 | * wakeup the thread for old dirty data writeback | 94 | * wakeup the thread for old dirty data writeback |
167 | */ | 95 | */ |
168 | work = kmalloc(sizeof(*work), GFP_ATOMIC); | 96 | work = kzalloc(sizeof(*work), GFP_ATOMIC); |
169 | if (work) { | 97 | if (!work) { |
170 | bdi_work_init(work, args); | 98 | if (bdi->wb.task) |
171 | bdi_queue_work(bdi, work); | 99 | wake_up_process(bdi->wb.task); |
172 | } else { | 100 | return; |
173 | struct bdi_writeback *wb = &bdi->wb; | ||
174 | |||
175 | if (wb->task) | ||
176 | wake_up_process(wb->task); | ||
177 | } | 101 | } |
178 | } | ||
179 | 102 | ||
180 | /** | 103 | work->sync_mode = WB_SYNC_NONE; |
181 | * bdi_queue_work_onstack - start and wait for writeback | 104 | work->nr_pages = nr_pages; |
182 | * @sb: write inodes from this super_block | 105 | work->range_cyclic = range_cyclic; |
183 | * | 106 | work->for_background = for_background; |
184 | * Description: | ||
185 | * This function initiates writeback and waits for the operation to | ||
186 | * complete. Callers must hold the sb s_umount semaphore for | ||
187 | * reading, to avoid having the super disappear before we are done. | ||
188 | */ | ||
189 | static void bdi_queue_work_onstack(struct wb_writeback_args *args) | ||
190 | { | ||
191 | struct bdi_work work; | ||
192 | |||
193 | bdi_work_init(&work, args); | ||
194 | __set_bit(WS_ONSTACK, &work.state); | ||
195 | 107 | ||
196 | bdi_queue_work(args->sb->s_bdi, &work); | 108 | bdi_queue_work(bdi, work); |
197 | bdi_wait_on_work_done(&work); | ||
198 | } | 109 | } |
199 | 110 | ||
200 | /** | 111 | /** |
@@ -210,13 +121,7 @@ static void bdi_queue_work_onstack(struct wb_writeback_args *args) | |||
210 | */ | 121 | */ |
211 | void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages) | 122 | void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages) |
212 | { | 123 | { |
213 | struct wb_writeback_args args = { | 124 | __bdi_start_writeback(bdi, nr_pages, true, false); |
214 | .sync_mode = WB_SYNC_NONE, | ||
215 | .nr_pages = nr_pages, | ||
216 | .range_cyclic = 1, | ||
217 | }; | ||
218 | |||
219 | bdi_alloc_queue_work(bdi, &args); | ||
220 | } | 125 | } |
221 | 126 | ||
222 | /** | 127 | /** |
@@ -230,13 +135,7 @@ void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages) | |||
230 | */ | 135 | */ |
231 | void bdi_start_background_writeback(struct backing_dev_info *bdi) | 136 | void bdi_start_background_writeback(struct backing_dev_info *bdi) |
232 | { | 137 | { |
233 | struct wb_writeback_args args = { | 138 | __bdi_start_writeback(bdi, LONG_MAX, true, true); |
234 | .sync_mode = WB_SYNC_NONE, | ||
235 | .nr_pages = LONG_MAX, | ||
236 | .for_background = 1, | ||
237 | .range_cyclic = 1, | ||
238 | }; | ||
239 | bdi_alloc_queue_work(bdi, &args); | ||
240 | } | 139 | } |
241 | 140 | ||
242 | /* | 141 | /* |
@@ -554,29 +453,41 @@ static bool pin_sb_for_writeback(struct super_block *sb) | |||
554 | 453 | ||
555 | /* | 454 | /* |
556 | * Write a portion of b_io inodes which belong to @sb. | 455 | * Write a portion of b_io inodes which belong to @sb. |
557 | * If @wbc->sb != NULL, then find and write all such | 456 | * |
457 | * If @only_this_sb is true, then find and write all such | ||
558 | * inodes. Otherwise write only ones which go sequentially | 458 | * inodes. Otherwise write only ones which go sequentially |
559 | * in reverse order. | 459 | * in reverse order. |
460 | * | ||
560 | * Return 1, if the caller writeback routine should be | 461 | * Return 1, if the caller writeback routine should be |
561 | * interrupted. Otherwise return 0. | 462 | * interrupted. Otherwise return 0. |
562 | */ | 463 | */ |
563 | static int writeback_sb_inodes(struct super_block *sb, | 464 | static int writeback_sb_inodes(struct super_block *sb, struct bdi_writeback *wb, |
564 | struct bdi_writeback *wb, | 465 | struct writeback_control *wbc, bool only_this_sb) |
565 | struct writeback_control *wbc) | ||
566 | { | 466 | { |
567 | while (!list_empty(&wb->b_io)) { | 467 | while (!list_empty(&wb->b_io)) { |
568 | long pages_skipped; | 468 | long pages_skipped; |
569 | struct inode *inode = list_entry(wb->b_io.prev, | 469 | struct inode *inode = list_entry(wb->b_io.prev, |
570 | struct inode, i_list); | 470 | struct inode, i_list); |
571 | if (wbc->sb && sb != inode->i_sb) { | 471 | |
572 | /* super block given and doesn't | 472 | if (inode->i_sb != sb) { |
573 | match, skip this inode */ | 473 | if (only_this_sb) { |
574 | redirty_tail(inode); | 474 | /* |
575 | continue; | 475 | * We only want to write back data for this |
576 | } | 476 | * superblock, move all inodes not belonging |
577 | if (sb != inode->i_sb) | 477 | * to it back onto the dirty list. |
578 | /* finish with this superblock */ | 478 | */ |
479 | redirty_tail(inode); | ||
480 | continue; | ||
481 | } | ||
482 | |||
483 | /* | ||
484 | * The inode belongs to a different superblock. | ||
485 | * Bounce back to the caller to unpin this and | ||
486 | * pin the next superblock. | ||
487 | */ | ||
579 | return 0; | 488 | return 0; |
489 | } | ||
490 | |||
580 | if (inode->i_state & (I_NEW | I_WILL_FREE)) { | 491 | if (inode->i_state & (I_NEW | I_WILL_FREE)) { |
581 | requeue_io(inode); | 492 | requeue_io(inode); |
582 | continue; | 493 | continue; |
@@ -614,8 +525,8 @@ static int writeback_sb_inodes(struct super_block *sb, | |||
614 | return 1; | 525 | return 1; |
615 | } | 526 | } |
616 | 527 | ||
617 | static void writeback_inodes_wb(struct bdi_writeback *wb, | 528 | void writeback_inodes_wb(struct bdi_writeback *wb, |
618 | struct writeback_control *wbc) | 529 | struct writeback_control *wbc) |
619 | { | 530 | { |
620 | int ret = 0; | 531 | int ret = 0; |
621 | 532 | ||
@@ -629,29 +540,12 @@ static void writeback_inodes_wb(struct bdi_writeback *wb, | |||
629 | struct inode, i_list); | 540 | struct inode, i_list); |
630 | struct super_block *sb = inode->i_sb; | 541 | struct super_block *sb = inode->i_sb; |
631 | 542 | ||
632 | if (wbc->sb) { | 543 | if (!pin_sb_for_writeback(sb)) { |
633 | /* | 544 | requeue_io(inode); |
634 | * We are requested to write out inodes for a specific | 545 | continue; |
635 | * superblock. This means we already have s_umount | ||
636 | * taken by the caller which also waits for us to | ||
637 | * complete the writeout. | ||
638 | */ | ||
639 | if (sb != wbc->sb) { | ||
640 | redirty_tail(inode); | ||
641 | continue; | ||
642 | } | ||
643 | |||
644 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | ||
645 | |||
646 | ret = writeback_sb_inodes(sb, wb, wbc); | ||
647 | } else { | ||
648 | if (!pin_sb_for_writeback(sb)) { | ||
649 | requeue_io(inode); | ||
650 | continue; | ||
651 | } | ||
652 | ret = writeback_sb_inodes(sb, wb, wbc); | ||
653 | drop_super(sb); | ||
654 | } | 546 | } |
547 | ret = writeback_sb_inodes(sb, wb, wbc, false); | ||
548 | drop_super(sb); | ||
655 | 549 | ||
656 | if (ret) | 550 | if (ret) |
657 | break; | 551 | break; |
@@ -660,11 +554,17 @@ static void writeback_inodes_wb(struct bdi_writeback *wb, | |||
660 | /* Leave any unwritten inodes on b_io */ | 554 | /* Leave any unwritten inodes on b_io */ |
661 | } | 555 | } |
662 | 556 | ||
663 | void writeback_inodes_wbc(struct writeback_control *wbc) | 557 | static void __writeback_inodes_sb(struct super_block *sb, |
558 | struct bdi_writeback *wb, struct writeback_control *wbc) | ||
664 | { | 559 | { |
665 | struct backing_dev_info *bdi = wbc->bdi; | 560 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); |
666 | 561 | ||
667 | writeback_inodes_wb(&bdi->wb, wbc); | 562 | wbc->wb_start = jiffies; /* livelock avoidance */ |
563 | spin_lock(&inode_lock); | ||
564 | if (!wbc->for_kupdate || list_empty(&wb->b_io)) | ||
565 | queue_io(wb, wbc->older_than_this); | ||
566 | writeback_sb_inodes(sb, wb, wbc, true); | ||
567 | spin_unlock(&inode_lock); | ||
668 | } | 568 | } |
669 | 569 | ||
670 | /* | 570 | /* |
@@ -702,16 +602,14 @@ static inline bool over_bground_thresh(void) | |||
702 | * all dirty pages if they are all attached to "old" mappings. | 602 | * all dirty pages if they are all attached to "old" mappings. |
703 | */ | 603 | */ |
704 | static long wb_writeback(struct bdi_writeback *wb, | 604 | static long wb_writeback(struct bdi_writeback *wb, |
705 | struct wb_writeback_args *args) | 605 | struct wb_writeback_work *work) |
706 | { | 606 | { |
707 | struct writeback_control wbc = { | 607 | struct writeback_control wbc = { |
708 | .bdi = wb->bdi, | 608 | .sync_mode = work->sync_mode, |
709 | .sb = args->sb, | ||
710 | .sync_mode = args->sync_mode, | ||
711 | .older_than_this = NULL, | 609 | .older_than_this = NULL, |
712 | .for_kupdate = args->for_kupdate, | 610 | .for_kupdate = work->for_kupdate, |
713 | .for_background = args->for_background, | 611 | .for_background = work->for_background, |
714 | .range_cyclic = args->range_cyclic, | 612 | .range_cyclic = work->range_cyclic, |
715 | }; | 613 | }; |
716 | unsigned long oldest_jif; | 614 | unsigned long oldest_jif; |
717 | long wrote = 0; | 615 | long wrote = 0; |
@@ -731,21 +629,24 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
731 | /* | 629 | /* |
732 | * Stop writeback when nr_pages has been consumed | 630 | * Stop writeback when nr_pages has been consumed |
733 | */ | 631 | */ |
734 | if (args->nr_pages <= 0) | 632 | if (work->nr_pages <= 0) |
735 | break; | 633 | break; |
736 | 634 | ||
737 | /* | 635 | /* |
738 | * For background writeout, stop when we are below the | 636 | * For background writeout, stop when we are below the |
739 | * background dirty threshold | 637 | * background dirty threshold |
740 | */ | 638 | */ |
741 | if (args->for_background && !over_bground_thresh()) | 639 | if (work->for_background && !over_bground_thresh()) |
742 | break; | 640 | break; |
743 | 641 | ||
744 | wbc.more_io = 0; | 642 | wbc.more_io = 0; |
745 | wbc.nr_to_write = MAX_WRITEBACK_PAGES; | 643 | wbc.nr_to_write = MAX_WRITEBACK_PAGES; |
746 | wbc.pages_skipped = 0; | 644 | wbc.pages_skipped = 0; |
747 | writeback_inodes_wb(wb, &wbc); | 645 | if (work->sb) |
748 | args->nr_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write; | 646 | __writeback_inodes_sb(work->sb, wb, &wbc); |
647 | else | ||
648 | writeback_inodes_wb(wb, &wbc); | ||
649 | work->nr_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write; | ||
749 | wrote += MAX_WRITEBACK_PAGES - wbc.nr_to_write; | 650 | wrote += MAX_WRITEBACK_PAGES - wbc.nr_to_write; |
750 | 651 | ||
751 | /* | 652 | /* |
@@ -781,31 +682,21 @@ static long wb_writeback(struct bdi_writeback *wb, | |||
781 | } | 682 | } |
782 | 683 | ||
783 | /* | 684 | /* |
784 | * Return the next bdi_work struct that hasn't been processed by this | 685 | * Return the next wb_writeback_work struct that hasn't been processed yet. |
785 | * wb thread yet. ->seen is initially set for each thread that exists | ||
786 | * for this device, when a thread first notices a piece of work it | ||
787 | * clears its bit. Depending on writeback type, the thread will notify | ||
788 | * completion on either receiving the work (WB_SYNC_NONE) or after | ||
789 | * it is done (WB_SYNC_ALL). | ||
790 | */ | 686 | */ |
791 | static struct bdi_work *get_next_work_item(struct backing_dev_info *bdi, | 687 | static struct wb_writeback_work * |
792 | struct bdi_writeback *wb) | 688 | get_next_work_item(struct backing_dev_info *bdi, struct bdi_writeback *wb) |
793 | { | 689 | { |
794 | struct bdi_work *work, *ret = NULL; | 690 | struct wb_writeback_work *work = NULL; |
795 | |||
796 | rcu_read_lock(); | ||
797 | 691 | ||
798 | list_for_each_entry_rcu(work, &bdi->work_list, list) { | 692 | spin_lock(&bdi->wb_lock); |
799 | if (!test_bit(wb->nr, &work->seen)) | 693 | if (!list_empty(&bdi->work_list)) { |
800 | continue; | 694 | work = list_entry(bdi->work_list.next, |
801 | clear_bit(wb->nr, &work->seen); | 695 | struct wb_writeback_work, list); |
802 | 696 | list_del_init(&work->list); | |
803 | ret = work; | ||
804 | break; | ||
805 | } | 697 | } |
806 | 698 | spin_unlock(&bdi->wb_lock); | |
807 | rcu_read_unlock(); | 699 | return work; |
808 | return ret; | ||
809 | } | 700 | } |
810 | 701 | ||
811 | static long wb_check_old_data_flush(struct bdi_writeback *wb) | 702 | static long wb_check_old_data_flush(struct bdi_writeback *wb) |
@@ -830,14 +721,14 @@ static long wb_check_old_data_flush(struct bdi_writeback *wb) | |||
830 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); | 721 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); |
831 | 722 | ||
832 | if (nr_pages) { | 723 | if (nr_pages) { |
833 | struct wb_writeback_args args = { | 724 | struct wb_writeback_work work = { |
834 | .nr_pages = nr_pages, | 725 | .nr_pages = nr_pages, |
835 | .sync_mode = WB_SYNC_NONE, | 726 | .sync_mode = WB_SYNC_NONE, |
836 | .for_kupdate = 1, | 727 | .for_kupdate = 1, |
837 | .range_cyclic = 1, | 728 | .range_cyclic = 1, |
838 | }; | 729 | }; |
839 | 730 | ||
840 | return wb_writeback(wb, &args); | 731 | return wb_writeback(wb, &work); |
841 | } | 732 | } |
842 | 733 | ||
843 | return 0; | 734 | return 0; |
@@ -849,33 +740,27 @@ static long wb_check_old_data_flush(struct bdi_writeback *wb) | |||
849 | long wb_do_writeback(struct bdi_writeback *wb, int force_wait) | 740 | long wb_do_writeback(struct bdi_writeback *wb, int force_wait) |
850 | { | 741 | { |
851 | struct backing_dev_info *bdi = wb->bdi; | 742 | struct backing_dev_info *bdi = wb->bdi; |
852 | struct bdi_work *work; | 743 | struct wb_writeback_work *work; |
853 | long wrote = 0; | 744 | long wrote = 0; |
854 | 745 | ||
855 | while ((work = get_next_work_item(bdi, wb)) != NULL) { | 746 | while ((work = get_next_work_item(bdi, wb)) != NULL) { |
856 | struct wb_writeback_args args = work->args; | ||
857 | |||
858 | /* | 747 | /* |
859 | * Override sync mode, in case we must wait for completion | 748 | * Override sync mode, in case we must wait for completion |
749 | * because this thread is exiting now. | ||
860 | */ | 750 | */ |
861 | if (force_wait) | 751 | if (force_wait) |
862 | work->args.sync_mode = args.sync_mode = WB_SYNC_ALL; | 752 | work->sync_mode = WB_SYNC_ALL; |
863 | |||
864 | /* | ||
865 | * If this isn't a data integrity operation, just notify | ||
866 | * that we have seen this work and we are now starting it. | ||
867 | */ | ||
868 | if (!test_bit(WS_ONSTACK, &work->state)) | ||
869 | wb_clear_pending(wb, work); | ||
870 | 753 | ||
871 | wrote += wb_writeback(wb, &args); | 754 | wrote += wb_writeback(wb, work); |
872 | 755 | ||
873 | /* | 756 | /* |
874 | * This is a data integrity writeback, so only do the | 757 | * Notify the caller of completion if this is a synchronous |
875 | * notification when we have completed the work. | 758 | * work item, otherwise just free it. |
876 | */ | 759 | */ |
877 | if (test_bit(WS_ONSTACK, &work->state)) | 760 | if (work->done) |
878 | wb_clear_pending(wb, work); | 761 | complete(work->done); |
762 | else | ||
763 | kfree(work); | ||
879 | } | 764 | } |
880 | 765 | ||
881 | /* | 766 | /* |
@@ -938,14 +823,9 @@ int bdi_writeback_task(struct bdi_writeback *wb) | |||
938 | void wakeup_flusher_threads(long nr_pages) | 823 | void wakeup_flusher_threads(long nr_pages) |
939 | { | 824 | { |
940 | struct backing_dev_info *bdi; | 825 | struct backing_dev_info *bdi; |
941 | struct wb_writeback_args args = { | ||
942 | .sync_mode = WB_SYNC_NONE, | ||
943 | }; | ||
944 | 826 | ||
945 | if (nr_pages) { | 827 | if (!nr_pages) { |
946 | args.nr_pages = nr_pages; | 828 | nr_pages = global_page_state(NR_FILE_DIRTY) + |
947 | } else { | ||
948 | args.nr_pages = global_page_state(NR_FILE_DIRTY) + | ||
949 | global_page_state(NR_UNSTABLE_NFS); | 829 | global_page_state(NR_UNSTABLE_NFS); |
950 | } | 830 | } |
951 | 831 | ||
@@ -953,7 +833,7 @@ void wakeup_flusher_threads(long nr_pages) | |||
953 | list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) { | 833 | list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) { |
954 | if (!bdi_has_dirty_io(bdi)) | 834 | if (!bdi_has_dirty_io(bdi)) |
955 | continue; | 835 | continue; |
956 | bdi_alloc_queue_work(bdi, &args); | 836 | __bdi_start_writeback(bdi, nr_pages, false, false); |
957 | } | 837 | } |
958 | rcu_read_unlock(); | 838 | rcu_read_unlock(); |
959 | } | 839 | } |
@@ -1162,17 +1042,20 @@ void writeback_inodes_sb(struct super_block *sb) | |||
1162 | { | 1042 | { |
1163 | unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY); | 1043 | unsigned long nr_dirty = global_page_state(NR_FILE_DIRTY); |
1164 | unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS); | 1044 | unsigned long nr_unstable = global_page_state(NR_UNSTABLE_NFS); |
1165 | struct wb_writeback_args args = { | 1045 | DECLARE_COMPLETION_ONSTACK(done); |
1046 | struct wb_writeback_work work = { | ||
1166 | .sb = sb, | 1047 | .sb = sb, |
1167 | .sync_mode = WB_SYNC_NONE, | 1048 | .sync_mode = WB_SYNC_NONE, |
1049 | .done = &done, | ||
1168 | }; | 1050 | }; |
1169 | 1051 | ||
1170 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | 1052 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); |
1171 | 1053 | ||
1172 | args.nr_pages = nr_dirty + nr_unstable + | 1054 | work.nr_pages = nr_dirty + nr_unstable + |
1173 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); | 1055 | (inodes_stat.nr_inodes - inodes_stat.nr_unused); |
1174 | 1056 | ||
1175 | bdi_queue_work_onstack(&args); | 1057 | bdi_queue_work(sb->s_bdi, &work); |
1058 | wait_for_completion(&done); | ||
1176 | } | 1059 | } |
1177 | EXPORT_SYMBOL(writeback_inodes_sb); | 1060 | EXPORT_SYMBOL(writeback_inodes_sb); |
1178 | 1061 | ||
@@ -1204,16 +1087,20 @@ EXPORT_SYMBOL(writeback_inodes_sb_if_idle); | |||
1204 | */ | 1087 | */ |
1205 | void sync_inodes_sb(struct super_block *sb) | 1088 | void sync_inodes_sb(struct super_block *sb) |
1206 | { | 1089 | { |
1207 | struct wb_writeback_args args = { | 1090 | DECLARE_COMPLETION_ONSTACK(done); |
1091 | struct wb_writeback_work work = { | ||
1208 | .sb = sb, | 1092 | .sb = sb, |
1209 | .sync_mode = WB_SYNC_ALL, | 1093 | .sync_mode = WB_SYNC_ALL, |
1210 | .nr_pages = LONG_MAX, | 1094 | .nr_pages = LONG_MAX, |
1211 | .range_cyclic = 0, | 1095 | .range_cyclic = 0, |
1096 | .done = &done, | ||
1212 | }; | 1097 | }; |
1213 | 1098 | ||
1214 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); | 1099 | WARN_ON(!rwsem_is_locked(&sb->s_umount)); |
1215 | 1100 | ||
1216 | bdi_queue_work_onstack(&args); | 1101 | bdi_queue_work(sb->s_bdi, &work); |
1102 | wait_for_completion(&done); | ||
1103 | |||
1217 | wait_sb_inodes(sb); | 1104 | wait_sb_inodes(sb); |
1218 | } | 1105 | } |
1219 | EXPORT_SYMBOL(sync_inodes_sb); | 1106 | EXPORT_SYMBOL(sync_inodes_sb); |
diff --git a/fs/fscache/Kconfig b/fs/fscache/Kconfig index cc94bb9563f2..3f6dfa989881 100644 --- a/fs/fscache/Kconfig +++ b/fs/fscache/Kconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | 1 | ||
2 | config FSCACHE | 2 | config FSCACHE |
3 | tristate "General filesystem local caching manager" | 3 | tristate "General filesystem local caching manager" |
4 | select SLOW_WORK | ||
5 | help | 4 | help |
6 | This option enables a generic filesystem caching manager that can be | 5 | This option enables a generic filesystem caching manager that can be |
7 | used by various network and other filesystems to cache data locally. | 6 | used by various network and other filesystems to cache data locally. |
diff --git a/fs/fscache/internal.h b/fs/fscache/internal.h index edd7434ab6e5..6a026441c5a6 100644 --- a/fs/fscache/internal.h +++ b/fs/fscache/internal.h | |||
@@ -82,6 +82,14 @@ extern unsigned fscache_defer_lookup; | |||
82 | extern unsigned fscache_defer_create; | 82 | extern unsigned fscache_defer_create; |
83 | extern unsigned fscache_debug; | 83 | extern unsigned fscache_debug; |
84 | extern struct kobject *fscache_root; | 84 | extern struct kobject *fscache_root; |
85 | extern struct workqueue_struct *fscache_object_wq; | ||
86 | extern struct workqueue_struct *fscache_op_wq; | ||
87 | DECLARE_PER_CPU(wait_queue_head_t, fscache_object_cong_wait); | ||
88 | |||
89 | static inline bool fscache_object_congested(void) | ||
90 | { | ||
91 | return workqueue_congested(WORK_CPU_UNBOUND, fscache_object_wq); | ||
92 | } | ||
85 | 93 | ||
86 | extern int fscache_wait_bit(void *); | 94 | extern int fscache_wait_bit(void *); |
87 | extern int fscache_wait_bit_interruptible(void *); | 95 | extern int fscache_wait_bit_interruptible(void *); |
diff --git a/fs/fscache/main.c b/fs/fscache/main.c index add6bdb53f04..f9d856773f79 100644 --- a/fs/fscache/main.c +++ b/fs/fscache/main.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/completion.h> | 16 | #include <linux/completion.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/seq_file.h> | ||
18 | #include "internal.h" | 19 | #include "internal.h" |
19 | 20 | ||
20 | MODULE_DESCRIPTION("FS Cache Manager"); | 21 | MODULE_DESCRIPTION("FS Cache Manager"); |
@@ -40,22 +41,105 @@ MODULE_PARM_DESC(fscache_debug, | |||
40 | "FS-Cache debugging mask"); | 41 | "FS-Cache debugging mask"); |
41 | 42 | ||
42 | struct kobject *fscache_root; | 43 | struct kobject *fscache_root; |
44 | struct workqueue_struct *fscache_object_wq; | ||
45 | struct workqueue_struct *fscache_op_wq; | ||
46 | |||
47 | DEFINE_PER_CPU(wait_queue_head_t, fscache_object_cong_wait); | ||
48 | |||
49 | /* these values serve as lower bounds, will be adjusted in fscache_init() */ | ||
50 | static unsigned fscache_object_max_active = 4; | ||
51 | static unsigned fscache_op_max_active = 2; | ||
52 | |||
53 | #ifdef CONFIG_SYSCTL | ||
54 | static struct ctl_table_header *fscache_sysctl_header; | ||
55 | |||
56 | static int fscache_max_active_sysctl(struct ctl_table *table, int write, | ||
57 | void __user *buffer, | ||
58 | size_t *lenp, loff_t *ppos) | ||
59 | { | ||
60 | struct workqueue_struct **wqp = table->extra1; | ||
61 | unsigned int *datap = table->data; | ||
62 | int ret; | ||
63 | |||
64 | ret = proc_dointvec(table, write, buffer, lenp, ppos); | ||
65 | if (ret == 0) | ||
66 | workqueue_set_max_active(*wqp, *datap); | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | ctl_table fscache_sysctls[] = { | ||
71 | { | ||
72 | .procname = "object_max_active", | ||
73 | .data = &fscache_object_max_active, | ||
74 | .maxlen = sizeof(unsigned), | ||
75 | .mode = 0644, | ||
76 | .proc_handler = fscache_max_active_sysctl, | ||
77 | .extra1 = &fscache_object_wq, | ||
78 | }, | ||
79 | { | ||
80 | .procname = "operation_max_active", | ||
81 | .data = &fscache_op_max_active, | ||
82 | .maxlen = sizeof(unsigned), | ||
83 | .mode = 0644, | ||
84 | .proc_handler = fscache_max_active_sysctl, | ||
85 | .extra1 = &fscache_op_wq, | ||
86 | }, | ||
87 | {} | ||
88 | }; | ||
89 | |||
90 | ctl_table fscache_sysctls_root[] = { | ||
91 | { | ||
92 | .procname = "fscache", | ||
93 | .mode = 0555, | ||
94 | .child = fscache_sysctls, | ||
95 | }, | ||
96 | {} | ||
97 | }; | ||
98 | #endif | ||
43 | 99 | ||
44 | /* | 100 | /* |
45 | * initialise the fs caching module | 101 | * initialise the fs caching module |
46 | */ | 102 | */ |
47 | static int __init fscache_init(void) | 103 | static int __init fscache_init(void) |
48 | { | 104 | { |
105 | unsigned int nr_cpus = num_possible_cpus(); | ||
106 | unsigned int cpu; | ||
49 | int ret; | 107 | int ret; |
50 | 108 | ||
51 | ret = slow_work_register_user(THIS_MODULE); | 109 | fscache_object_max_active = |
52 | if (ret < 0) | 110 | clamp_val(nr_cpus, |
53 | goto error_slow_work; | 111 | fscache_object_max_active, WQ_UNBOUND_MAX_ACTIVE); |
112 | |||
113 | ret = -ENOMEM; | ||
114 | fscache_object_wq = alloc_workqueue("fscache_object", WQ_UNBOUND, | ||
115 | fscache_object_max_active); | ||
116 | if (!fscache_object_wq) | ||
117 | goto error_object_wq; | ||
118 | |||
119 | fscache_op_max_active = | ||
120 | clamp_val(fscache_object_max_active / 2, | ||
121 | fscache_op_max_active, WQ_UNBOUND_MAX_ACTIVE); | ||
122 | |||
123 | ret = -ENOMEM; | ||
124 | fscache_op_wq = alloc_workqueue("fscache_operation", WQ_UNBOUND, | ||
125 | fscache_op_max_active); | ||
126 | if (!fscache_op_wq) | ||
127 | goto error_op_wq; | ||
128 | |||
129 | for_each_possible_cpu(cpu) | ||
130 | init_waitqueue_head(&per_cpu(fscache_object_cong_wait, cpu)); | ||
54 | 131 | ||
55 | ret = fscache_proc_init(); | 132 | ret = fscache_proc_init(); |
56 | if (ret < 0) | 133 | if (ret < 0) |
57 | goto error_proc; | 134 | goto error_proc; |
58 | 135 | ||
136 | #ifdef CONFIG_SYSCTL | ||
137 | ret = -ENOMEM; | ||
138 | fscache_sysctl_header = register_sysctl_table(fscache_sysctls_root); | ||
139 | if (!fscache_sysctl_header) | ||
140 | goto error_sysctl; | ||
141 | #endif | ||
142 | |||
59 | fscache_cookie_jar = kmem_cache_create("fscache_cookie_jar", | 143 | fscache_cookie_jar = kmem_cache_create("fscache_cookie_jar", |
60 | sizeof(struct fscache_cookie), | 144 | sizeof(struct fscache_cookie), |
61 | 0, | 145 | 0, |
@@ -78,10 +162,16 @@ static int __init fscache_init(void) | |||
78 | error_kobj: | 162 | error_kobj: |
79 | kmem_cache_destroy(fscache_cookie_jar); | 163 | kmem_cache_destroy(fscache_cookie_jar); |
80 | error_cookie_jar: | 164 | error_cookie_jar: |
165 | #ifdef CONFIG_SYSCTL | ||
166 | unregister_sysctl_table(fscache_sysctl_header); | ||
167 | error_sysctl: | ||
168 | #endif | ||
81 | fscache_proc_cleanup(); | 169 | fscache_proc_cleanup(); |
82 | error_proc: | 170 | error_proc: |
83 | slow_work_unregister_user(THIS_MODULE); | 171 | destroy_workqueue(fscache_op_wq); |
84 | error_slow_work: | 172 | error_op_wq: |
173 | destroy_workqueue(fscache_object_wq); | ||
174 | error_object_wq: | ||
85 | return ret; | 175 | return ret; |
86 | } | 176 | } |
87 | 177 | ||
@@ -96,8 +186,12 @@ static void __exit fscache_exit(void) | |||
96 | 186 | ||
97 | kobject_put(fscache_root); | 187 | kobject_put(fscache_root); |
98 | kmem_cache_destroy(fscache_cookie_jar); | 188 | kmem_cache_destroy(fscache_cookie_jar); |
189 | #ifdef CONFIG_SYSCTL | ||
190 | unregister_sysctl_table(fscache_sysctl_header); | ||
191 | #endif | ||
99 | fscache_proc_cleanup(); | 192 | fscache_proc_cleanup(); |
100 | slow_work_unregister_user(THIS_MODULE); | 193 | destroy_workqueue(fscache_op_wq); |
194 | destroy_workqueue(fscache_object_wq); | ||
101 | printk(KERN_NOTICE "FS-Cache: Unloaded\n"); | 195 | printk(KERN_NOTICE "FS-Cache: Unloaded\n"); |
102 | } | 196 | } |
103 | 197 | ||
diff --git a/fs/fscache/object-list.c b/fs/fscache/object-list.c index 4a8eb31c5338..ebe29c581380 100644 --- a/fs/fscache/object-list.c +++ b/fs/fscache/object-list.c | |||
@@ -34,8 +34,8 @@ struct fscache_objlist_data { | |||
34 | #define FSCACHE_OBJLIST_CONFIG_NOREADS 0x00000200 /* show objects without active reads */ | 34 | #define FSCACHE_OBJLIST_CONFIG_NOREADS 0x00000200 /* show objects without active reads */ |
35 | #define FSCACHE_OBJLIST_CONFIG_EVENTS 0x00000400 /* show objects with events */ | 35 | #define FSCACHE_OBJLIST_CONFIG_EVENTS 0x00000400 /* show objects with events */ |
36 | #define FSCACHE_OBJLIST_CONFIG_NOEVENTS 0x00000800 /* show objects without no events */ | 36 | #define FSCACHE_OBJLIST_CONFIG_NOEVENTS 0x00000800 /* show objects without no events */ |
37 | #define FSCACHE_OBJLIST_CONFIG_WORK 0x00001000 /* show objects with slow work */ | 37 | #define FSCACHE_OBJLIST_CONFIG_WORK 0x00001000 /* show objects with work */ |
38 | #define FSCACHE_OBJLIST_CONFIG_NOWORK 0x00002000 /* show objects without slow work */ | 38 | #define FSCACHE_OBJLIST_CONFIG_NOWORK 0x00002000 /* show objects without work */ |
39 | 39 | ||
40 | u8 buf[512]; /* key and aux data buffer */ | 40 | u8 buf[512]; /* key and aux data buffer */ |
41 | }; | 41 | }; |
@@ -231,12 +231,11 @@ static int fscache_objlist_show(struct seq_file *m, void *v) | |||
231 | READS, NOREADS); | 231 | READS, NOREADS); |
232 | FILTER(obj->events & obj->event_mask, | 232 | FILTER(obj->events & obj->event_mask, |
233 | EVENTS, NOEVENTS); | 233 | EVENTS, NOEVENTS); |
234 | FILTER(obj->work.flags & ~(1UL << SLOW_WORK_VERY_SLOW), | 234 | FILTER(work_busy(&obj->work), WORK, NOWORK); |
235 | WORK, NOWORK); | ||
236 | } | 235 | } |
237 | 236 | ||
238 | seq_printf(m, | 237 | seq_printf(m, |
239 | "%8x %8x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %1lx %1lx | ", | 238 | "%8x %8x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %1lx %1x | ", |
240 | obj->debug_id, | 239 | obj->debug_id, |
241 | obj->parent ? obj->parent->debug_id : -1, | 240 | obj->parent ? obj->parent->debug_id : -1, |
242 | fscache_object_states_short[obj->state], | 241 | fscache_object_states_short[obj->state], |
@@ -249,7 +248,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v) | |||
249 | obj->event_mask & FSCACHE_OBJECT_EVENTS_MASK, | 248 | obj->event_mask & FSCACHE_OBJECT_EVENTS_MASK, |
250 | obj->events, | 249 | obj->events, |
251 | obj->flags, | 250 | obj->flags, |
252 | obj->work.flags); | 251 | work_busy(&obj->work)); |
253 | 252 | ||
254 | no_cookie = true; | 253 | no_cookie = true; |
255 | keylen = auxlen = 0; | 254 | keylen = auxlen = 0; |
diff --git a/fs/fscache/object.c b/fs/fscache/object.c index 0b589a9b4ffc..b6b897c550ac 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | #define FSCACHE_DEBUG_LEVEL COOKIE | 15 | #define FSCACHE_DEBUG_LEVEL COOKIE |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/seq_file.h> | ||
18 | #include "internal.h" | 17 | #include "internal.h" |
19 | 18 | ||
20 | const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = { | 19 | const char *fscache_object_states[FSCACHE_OBJECT__NSTATES] = { |
@@ -50,12 +49,8 @@ const char fscache_object_states_short[FSCACHE_OBJECT__NSTATES][5] = { | |||
50 | [FSCACHE_OBJECT_DEAD] = "DEAD", | 49 | [FSCACHE_OBJECT_DEAD] = "DEAD", |
51 | }; | 50 | }; |
52 | 51 | ||
53 | static void fscache_object_slow_work_put_ref(struct slow_work *); | 52 | static int fscache_get_object(struct fscache_object *); |
54 | static int fscache_object_slow_work_get_ref(struct slow_work *); | 53 | static void fscache_put_object(struct fscache_object *); |
55 | static void fscache_object_slow_work_execute(struct slow_work *); | ||
56 | #ifdef CONFIG_SLOW_WORK_DEBUG | ||
57 | static void fscache_object_slow_work_desc(struct slow_work *, struct seq_file *); | ||
58 | #endif | ||
59 | static void fscache_initialise_object(struct fscache_object *); | 54 | static void fscache_initialise_object(struct fscache_object *); |
60 | static void fscache_lookup_object(struct fscache_object *); | 55 | static void fscache_lookup_object(struct fscache_object *); |
61 | static void fscache_object_available(struct fscache_object *); | 56 | static void fscache_object_available(struct fscache_object *); |
@@ -64,17 +59,6 @@ static void fscache_withdraw_object(struct fscache_object *); | |||
64 | static void fscache_enqueue_dependents(struct fscache_object *); | 59 | static void fscache_enqueue_dependents(struct fscache_object *); |
65 | static void fscache_dequeue_object(struct fscache_object *); | 60 | static void fscache_dequeue_object(struct fscache_object *); |
66 | 61 | ||
67 | const struct slow_work_ops fscache_object_slow_work_ops = { | ||
68 | .owner = THIS_MODULE, | ||
69 | .get_ref = fscache_object_slow_work_get_ref, | ||
70 | .put_ref = fscache_object_slow_work_put_ref, | ||
71 | .execute = fscache_object_slow_work_execute, | ||
72 | #ifdef CONFIG_SLOW_WORK_DEBUG | ||
73 | .desc = fscache_object_slow_work_desc, | ||
74 | #endif | ||
75 | }; | ||
76 | EXPORT_SYMBOL(fscache_object_slow_work_ops); | ||
77 | |||
78 | /* | 62 | /* |
79 | * we need to notify the parent when an op completes that we had outstanding | 63 | * we need to notify the parent when an op completes that we had outstanding |
80 | * upon it | 64 | * upon it |
@@ -345,7 +329,7 @@ unsupported_event: | |||
345 | /* | 329 | /* |
346 | * execute an object | 330 | * execute an object |
347 | */ | 331 | */ |
348 | static void fscache_object_slow_work_execute(struct slow_work *work) | 332 | void fscache_object_work_func(struct work_struct *work) |
349 | { | 333 | { |
350 | struct fscache_object *object = | 334 | struct fscache_object *object = |
351 | container_of(work, struct fscache_object, work); | 335 | container_of(work, struct fscache_object, work); |
@@ -359,23 +343,9 @@ static void fscache_object_slow_work_execute(struct slow_work *work) | |||
359 | if (object->events & object->event_mask) | 343 | if (object->events & object->event_mask) |
360 | fscache_enqueue_object(object); | 344 | fscache_enqueue_object(object); |
361 | clear_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); | 345 | clear_bit(FSCACHE_OBJECT_EV_REQUEUE, &object->events); |
346 | fscache_put_object(object); | ||
362 | } | 347 | } |
363 | 348 | EXPORT_SYMBOL(fscache_object_work_func); | |
364 | /* | ||
365 | * describe an object for slow-work debugging | ||
366 | */ | ||
367 | #ifdef CONFIG_SLOW_WORK_DEBUG | ||
368 | static void fscache_object_slow_work_desc(struct slow_work *work, | ||
369 | struct seq_file *m) | ||
370 | { | ||
371 | struct fscache_object *object = | ||
372 | container_of(work, struct fscache_object, work); | ||
373 | |||
374 | seq_printf(m, "FSC: OBJ%x: %s", | ||
375 | object->debug_id, | ||
376 | fscache_object_states_short[object->state]); | ||
377 | } | ||
378 | #endif | ||
379 | 349 | ||
380 | /* | 350 | /* |
381 | * initialise an object | 351 | * initialise an object |
@@ -393,7 +363,6 @@ static void fscache_initialise_object(struct fscache_object *object) | |||
393 | _enter(""); | 363 | _enter(""); |
394 | ASSERT(object->cookie != NULL); | 364 | ASSERT(object->cookie != NULL); |
395 | ASSERT(object->cookie->parent != NULL); | 365 | ASSERT(object->cookie->parent != NULL); |
396 | ASSERT(list_empty(&object->work.link)); | ||
397 | 366 | ||
398 | if (object->events & ((1 << FSCACHE_OBJECT_EV_ERROR) | | 367 | if (object->events & ((1 << FSCACHE_OBJECT_EV_ERROR) | |
399 | (1 << FSCACHE_OBJECT_EV_RELEASE) | | 368 | (1 << FSCACHE_OBJECT_EV_RELEASE) | |
@@ -671,10 +640,8 @@ static void fscache_drop_object(struct fscache_object *object) | |||
671 | object->parent = NULL; | 640 | object->parent = NULL; |
672 | } | 641 | } |
673 | 642 | ||
674 | /* this just shifts the object release to the slow work processor */ | 643 | /* this just shifts the object release to the work processor */ |
675 | fscache_stat(&fscache_n_cop_put_object); | 644 | fscache_put_object(object); |
676 | object->cache->ops->put_object(object); | ||
677 | fscache_stat_d(&fscache_n_cop_put_object); | ||
678 | 645 | ||
679 | _leave(""); | 646 | _leave(""); |
680 | } | 647 | } |
@@ -758,12 +725,10 @@ void fscache_withdrawing_object(struct fscache_cache *cache, | |||
758 | } | 725 | } |
759 | 726 | ||
760 | /* | 727 | /* |
761 | * allow the slow work item processor to get a ref on an object | 728 | * get a ref on an object |
762 | */ | 729 | */ |
763 | static int fscache_object_slow_work_get_ref(struct slow_work *work) | 730 | static int fscache_get_object(struct fscache_object *object) |
764 | { | 731 | { |
765 | struct fscache_object *object = | ||
766 | container_of(work, struct fscache_object, work); | ||
767 | int ret; | 732 | int ret; |
768 | 733 | ||
769 | fscache_stat(&fscache_n_cop_grab_object); | 734 | fscache_stat(&fscache_n_cop_grab_object); |
@@ -773,13 +738,10 @@ static int fscache_object_slow_work_get_ref(struct slow_work *work) | |||
773 | } | 738 | } |
774 | 739 | ||
775 | /* | 740 | /* |
776 | * allow the slow work item processor to discard a ref on a work item | 741 | * discard a ref on a work item |
777 | */ | 742 | */ |
778 | static void fscache_object_slow_work_put_ref(struct slow_work *work) | 743 | static void fscache_put_object(struct fscache_object *object) |
779 | { | 744 | { |
780 | struct fscache_object *object = | ||
781 | container_of(work, struct fscache_object, work); | ||
782 | |||
783 | fscache_stat(&fscache_n_cop_put_object); | 745 | fscache_stat(&fscache_n_cop_put_object); |
784 | object->cache->ops->put_object(object); | 746 | object->cache->ops->put_object(object); |
785 | fscache_stat_d(&fscache_n_cop_put_object); | 747 | fscache_stat_d(&fscache_n_cop_put_object); |
@@ -792,8 +754,48 @@ void fscache_enqueue_object(struct fscache_object *object) | |||
792 | { | 754 | { |
793 | _enter("{OBJ%x}", object->debug_id); | 755 | _enter("{OBJ%x}", object->debug_id); |
794 | 756 | ||
795 | slow_work_enqueue(&object->work); | 757 | if (fscache_get_object(object) >= 0) { |
758 | wait_queue_head_t *cong_wq = | ||
759 | &get_cpu_var(fscache_object_cong_wait); | ||
760 | |||
761 | if (queue_work(fscache_object_wq, &object->work)) { | ||
762 | if (fscache_object_congested()) | ||
763 | wake_up(cong_wq); | ||
764 | } else | ||
765 | fscache_put_object(object); | ||
766 | |||
767 | put_cpu_var(fscache_object_cong_wait); | ||
768 | } | ||
769 | } | ||
770 | |||
771 | /** | ||
772 | * fscache_object_sleep_till_congested - Sleep until object wq is congested | ||
773 | * @timoutp: Scheduler sleep timeout | ||
774 | * | ||
775 | * Allow an object handler to sleep until the object workqueue is congested. | ||
776 | * | ||
777 | * The caller must set up a wake up event before calling this and must have set | ||
778 | * the appropriate sleep mode (such as TASK_UNINTERRUPTIBLE) and tested its own | ||
779 | * condition before calling this function as no test is made here. | ||
780 | * | ||
781 | * %true is returned if the object wq is congested, %false otherwise. | ||
782 | */ | ||
783 | bool fscache_object_sleep_till_congested(signed long *timeoutp) | ||
784 | { | ||
785 | wait_queue_head_t *cong_wq = &__get_cpu_var(fscache_object_cong_wait); | ||
786 | DEFINE_WAIT(wait); | ||
787 | |||
788 | if (fscache_object_congested()) | ||
789 | return true; | ||
790 | |||
791 | add_wait_queue_exclusive(cong_wq, &wait); | ||
792 | if (!fscache_object_congested()) | ||
793 | *timeoutp = schedule_timeout(*timeoutp); | ||
794 | finish_wait(cong_wq, &wait); | ||
795 | |||
796 | return fscache_object_congested(); | ||
796 | } | 797 | } |
798 | EXPORT_SYMBOL_GPL(fscache_object_sleep_till_congested); | ||
797 | 799 | ||
798 | /* | 800 | /* |
799 | * enqueue the dependents of an object for metadata-type processing | 801 | * enqueue the dependents of an object for metadata-type processing |
@@ -819,9 +821,7 @@ static void fscache_enqueue_dependents(struct fscache_object *object) | |||
819 | 821 | ||
820 | /* sort onto appropriate lists */ | 822 | /* sort onto appropriate lists */ |
821 | fscache_enqueue_object(dep); | 823 | fscache_enqueue_object(dep); |
822 | fscache_stat(&fscache_n_cop_put_object); | 824 | fscache_put_object(dep); |
823 | dep->cache->ops->put_object(dep); | ||
824 | fscache_stat_d(&fscache_n_cop_put_object); | ||
825 | 825 | ||
826 | if (!list_empty(&object->dependents)) | 826 | if (!list_empty(&object->dependents)) |
827 | cond_resched_lock(&object->lock); | 827 | cond_resched_lock(&object->lock); |
diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c index f17cecafae44..b9f34eaede09 100644 --- a/fs/fscache/operation.c +++ b/fs/fscache/operation.c | |||
@@ -42,16 +42,12 @@ void fscache_enqueue_operation(struct fscache_operation *op) | |||
42 | 42 | ||
43 | fscache_stat(&fscache_n_op_enqueue); | 43 | fscache_stat(&fscache_n_op_enqueue); |
44 | switch (op->flags & FSCACHE_OP_TYPE) { | 44 | switch (op->flags & FSCACHE_OP_TYPE) { |
45 | case FSCACHE_OP_FAST: | 45 | case FSCACHE_OP_ASYNC: |
46 | _debug("queue fast"); | 46 | _debug("queue async"); |
47 | atomic_inc(&op->usage); | 47 | atomic_inc(&op->usage); |
48 | if (!schedule_work(&op->fast_work)) | 48 | if (!queue_work(fscache_op_wq, &op->work)) |
49 | fscache_put_operation(op); | 49 | fscache_put_operation(op); |
50 | break; | 50 | break; |
51 | case FSCACHE_OP_SLOW: | ||
52 | _debug("queue slow"); | ||
53 | slow_work_enqueue(&op->slow_work); | ||
54 | break; | ||
55 | case FSCACHE_OP_MYTHREAD: | 51 | case FSCACHE_OP_MYTHREAD: |
56 | _debug("queue for caller's attention"); | 52 | _debug("queue for caller's attention"); |
57 | break; | 53 | break; |
@@ -455,36 +451,13 @@ void fscache_operation_gc(struct work_struct *work) | |||
455 | } | 451 | } |
456 | 452 | ||
457 | /* | 453 | /* |
458 | * allow the slow work item processor to get a ref on an operation | 454 | * execute an operation using fs_op_wq to provide processing context - |
459 | */ | 455 | * the caller holds a ref to this object, so we don't need to hold one |
460 | static int fscache_op_get_ref(struct slow_work *work) | ||
461 | { | ||
462 | struct fscache_operation *op = | ||
463 | container_of(work, struct fscache_operation, slow_work); | ||
464 | |||
465 | atomic_inc(&op->usage); | ||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | /* | ||
470 | * allow the slow work item processor to discard a ref on an operation | ||
471 | */ | ||
472 | static void fscache_op_put_ref(struct slow_work *work) | ||
473 | { | ||
474 | struct fscache_operation *op = | ||
475 | container_of(work, struct fscache_operation, slow_work); | ||
476 | |||
477 | fscache_put_operation(op); | ||
478 | } | ||
479 | |||
480 | /* | ||
481 | * execute an operation using the slow thread pool to provide processing context | ||
482 | * - the caller holds a ref to this object, so we don't need to hold one | ||
483 | */ | 456 | */ |
484 | static void fscache_op_execute(struct slow_work *work) | 457 | void fscache_op_work_func(struct work_struct *work) |
485 | { | 458 | { |
486 | struct fscache_operation *op = | 459 | struct fscache_operation *op = |
487 | container_of(work, struct fscache_operation, slow_work); | 460 | container_of(work, struct fscache_operation, work); |
488 | unsigned long start; | 461 | unsigned long start; |
489 | 462 | ||
490 | _enter("{OBJ%x OP%x,%d}", | 463 | _enter("{OBJ%x OP%x,%d}", |
@@ -494,31 +467,7 @@ static void fscache_op_execute(struct slow_work *work) | |||
494 | start = jiffies; | 467 | start = jiffies; |
495 | op->processor(op); | 468 | op->processor(op); |
496 | fscache_hist(fscache_ops_histogram, start); | 469 | fscache_hist(fscache_ops_histogram, start); |
470 | fscache_put_operation(op); | ||
497 | 471 | ||
498 | _leave(""); | 472 | _leave(""); |
499 | } | 473 | } |
500 | |||
501 | /* | ||
502 | * describe an operation for slow-work debugging | ||
503 | */ | ||
504 | #ifdef CONFIG_SLOW_WORK_DEBUG | ||
505 | static void fscache_op_desc(struct slow_work *work, struct seq_file *m) | ||
506 | { | ||
507 | struct fscache_operation *op = | ||
508 | container_of(work, struct fscache_operation, slow_work); | ||
509 | |||
510 | seq_printf(m, "FSC: OBJ%x OP%x: %s/%s fl=%lx", | ||
511 | op->object->debug_id, op->debug_id, | ||
512 | op->name, op->state, op->flags); | ||
513 | } | ||
514 | #endif | ||
515 | |||
516 | const struct slow_work_ops fscache_op_slow_work_ops = { | ||
517 | .owner = THIS_MODULE, | ||
518 | .get_ref = fscache_op_get_ref, | ||
519 | .put_ref = fscache_op_put_ref, | ||
520 | .execute = fscache_op_execute, | ||
521 | #ifdef CONFIG_SLOW_WORK_DEBUG | ||
522 | .desc = fscache_op_desc, | ||
523 | #endif | ||
524 | }; | ||
diff --git a/fs/fscache/page.c b/fs/fscache/page.c index 723b889fd219..41c441c2058d 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c | |||
@@ -105,7 +105,7 @@ bool __fscache_maybe_release_page(struct fscache_cookie *cookie, | |||
105 | 105 | ||
106 | page_busy: | 106 | page_busy: |
107 | /* we might want to wait here, but that could deadlock the allocator as | 107 | /* we might want to wait here, but that could deadlock the allocator as |
108 | * the slow-work threads writing to the cache may all end up sleeping | 108 | * the work threads writing to the cache may all end up sleeping |
109 | * on memory allocation */ | 109 | * on memory allocation */ |
110 | fscache_stat(&fscache_n_store_vmscan_busy); | 110 | fscache_stat(&fscache_n_store_vmscan_busy); |
111 | return false; | 111 | return false; |
@@ -188,9 +188,8 @@ int __fscache_attr_changed(struct fscache_cookie *cookie) | |||
188 | return -ENOMEM; | 188 | return -ENOMEM; |
189 | } | 189 | } |
190 | 190 | ||
191 | fscache_operation_init(op, NULL); | 191 | fscache_operation_init(op, fscache_attr_changed_op, NULL); |
192 | fscache_operation_init_slow(op, fscache_attr_changed_op); | 192 | op->flags = FSCACHE_OP_ASYNC | (1 << FSCACHE_OP_EXCLUSIVE); |
193 | op->flags = FSCACHE_OP_SLOW | (1 << FSCACHE_OP_EXCLUSIVE); | ||
194 | fscache_set_op_name(op, "Attr"); | 193 | fscache_set_op_name(op, "Attr"); |
195 | 194 | ||
196 | spin_lock(&cookie->lock); | 195 | spin_lock(&cookie->lock); |
@@ -218,24 +217,6 @@ nobufs: | |||
218 | EXPORT_SYMBOL(__fscache_attr_changed); | 217 | EXPORT_SYMBOL(__fscache_attr_changed); |
219 | 218 | ||
220 | /* | 219 | /* |
221 | * handle secondary execution given to a retrieval op on behalf of the | ||
222 | * cache | ||
223 | */ | ||
224 | static void fscache_retrieval_work(struct work_struct *work) | ||
225 | { | ||
226 | struct fscache_retrieval *op = | ||
227 | container_of(work, struct fscache_retrieval, op.fast_work); | ||
228 | unsigned long start; | ||
229 | |||
230 | _enter("{OP%x}", op->op.debug_id); | ||
231 | |||
232 | start = jiffies; | ||
233 | op->op.processor(&op->op); | ||
234 | fscache_hist(fscache_ops_histogram, start); | ||
235 | fscache_put_operation(&op->op); | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * release a retrieval op reference | 220 | * release a retrieval op reference |
240 | */ | 221 | */ |
241 | static void fscache_release_retrieval_op(struct fscache_operation *_op) | 222 | static void fscache_release_retrieval_op(struct fscache_operation *_op) |
@@ -269,13 +250,12 @@ static struct fscache_retrieval *fscache_alloc_retrieval( | |||
269 | return NULL; | 250 | return NULL; |
270 | } | 251 | } |
271 | 252 | ||
272 | fscache_operation_init(&op->op, fscache_release_retrieval_op); | 253 | fscache_operation_init(&op->op, NULL, fscache_release_retrieval_op); |
273 | op->op.flags = FSCACHE_OP_MYTHREAD | (1 << FSCACHE_OP_WAITING); | 254 | op->op.flags = FSCACHE_OP_MYTHREAD | (1 << FSCACHE_OP_WAITING); |
274 | op->mapping = mapping; | 255 | op->mapping = mapping; |
275 | op->end_io_func = end_io_func; | 256 | op->end_io_func = end_io_func; |
276 | op->context = context; | 257 | op->context = context; |
277 | op->start_time = jiffies; | 258 | op->start_time = jiffies; |
278 | INIT_WORK(&op->op.fast_work, fscache_retrieval_work); | ||
279 | INIT_LIST_HEAD(&op->to_do); | 259 | INIT_LIST_HEAD(&op->to_do); |
280 | fscache_set_op_name(&op->op, "Retr"); | 260 | fscache_set_op_name(&op->op, "Retr"); |
281 | return op; | 261 | return op; |
@@ -795,9 +775,9 @@ int __fscache_write_page(struct fscache_cookie *cookie, | |||
795 | if (!op) | 775 | if (!op) |
796 | goto nomem; | 776 | goto nomem; |
797 | 777 | ||
798 | fscache_operation_init(&op->op, fscache_release_write_op); | 778 | fscache_operation_init(&op->op, fscache_write_op, |
799 | fscache_operation_init_slow(&op->op, fscache_write_op); | 779 | fscache_release_write_op); |
800 | op->op.flags = FSCACHE_OP_SLOW | (1 << FSCACHE_OP_WAITING); | 780 | op->op.flags = FSCACHE_OP_ASYNC | (1 << FSCACHE_OP_WAITING); |
801 | fscache_set_op_name(&op->op, "Write1"); | 781 | fscache_set_op_name(&op->op, "Write1"); |
802 | 782 | ||
803 | ret = radix_tree_preload(gfp & ~__GFP_HIGHMEM); | 783 | ret = radix_tree_preload(gfp & ~__GFP_HIGHMEM); |
@@ -852,7 +832,7 @@ int __fscache_write_page(struct fscache_cookie *cookie, | |||
852 | fscache_stat(&fscache_n_store_ops); | 832 | fscache_stat(&fscache_n_store_ops); |
853 | fscache_stat(&fscache_n_stores_ok); | 833 | fscache_stat(&fscache_n_stores_ok); |
854 | 834 | ||
855 | /* the slow work queue now carries its own ref on the object */ | 835 | /* the work queue now carries its own ref on the object */ |
856 | fscache_put_operation(&op->op); | 836 | fscache_put_operation(&op->op); |
857 | _leave(" = 0"); | 837 | _leave(" = 0"); |
858 | return 0; | 838 | return 0; |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 9424796d6634..69ad053ffd78 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -239,7 +239,6 @@ static u64 fuse_get_unique(struct fuse_conn *fc) | |||
239 | 239 | ||
240 | static void queue_request(struct fuse_conn *fc, struct fuse_req *req) | 240 | static void queue_request(struct fuse_conn *fc, struct fuse_req *req) |
241 | { | 241 | { |
242 | req->in.h.unique = fuse_get_unique(fc); | ||
243 | req->in.h.len = sizeof(struct fuse_in_header) + | 242 | req->in.h.len = sizeof(struct fuse_in_header) + |
244 | len_args(req->in.numargs, (struct fuse_arg *) req->in.args); | 243 | len_args(req->in.numargs, (struct fuse_arg *) req->in.args); |
245 | list_add_tail(&req->list, &fc->pending); | 244 | list_add_tail(&req->list, &fc->pending); |
@@ -261,6 +260,7 @@ static void flush_bg_queue(struct fuse_conn *fc) | |||
261 | req = list_entry(fc->bg_queue.next, struct fuse_req, list); | 260 | req = list_entry(fc->bg_queue.next, struct fuse_req, list); |
262 | list_del(&req->list); | 261 | list_del(&req->list); |
263 | fc->active_background++; | 262 | fc->active_background++; |
263 | req->in.h.unique = fuse_get_unique(fc); | ||
264 | queue_request(fc, req); | 264 | queue_request(fc, req); |
265 | } | 265 | } |
266 | } | 266 | } |
@@ -398,6 +398,7 @@ void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) | |||
398 | else if (fc->conn_error) | 398 | else if (fc->conn_error) |
399 | req->out.h.error = -ECONNREFUSED; | 399 | req->out.h.error = -ECONNREFUSED; |
400 | else { | 400 | else { |
401 | req->in.h.unique = fuse_get_unique(fc); | ||
401 | queue_request(fc, req); | 402 | queue_request(fc, req); |
402 | /* acquire extra reference, since request is still needed | 403 | /* acquire extra reference, since request is still needed |
403 | after request_end() */ | 404 | after request_end() */ |
@@ -450,6 +451,23 @@ void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req) | |||
450 | } | 451 | } |
451 | EXPORT_SYMBOL_GPL(fuse_request_send_background); | 452 | EXPORT_SYMBOL_GPL(fuse_request_send_background); |
452 | 453 | ||
454 | static int fuse_request_send_notify_reply(struct fuse_conn *fc, | ||
455 | struct fuse_req *req, u64 unique) | ||
456 | { | ||
457 | int err = -ENODEV; | ||
458 | |||
459 | req->isreply = 0; | ||
460 | req->in.h.unique = unique; | ||
461 | spin_lock(&fc->lock); | ||
462 | if (fc->connected) { | ||
463 | queue_request(fc, req); | ||
464 | err = 0; | ||
465 | } | ||
466 | spin_unlock(&fc->lock); | ||
467 | |||
468 | return err; | ||
469 | } | ||
470 | |||
453 | /* | 471 | /* |
454 | * Called under fc->lock | 472 | * Called under fc->lock |
455 | * | 473 | * |
@@ -535,13 +553,13 @@ static void fuse_copy_finish(struct fuse_copy_state *cs) | |||
535 | if (!cs->write) { | 553 | if (!cs->write) { |
536 | buf->ops->unmap(cs->pipe, buf, cs->mapaddr); | 554 | buf->ops->unmap(cs->pipe, buf, cs->mapaddr); |
537 | } else { | 555 | } else { |
538 | kunmap_atomic(cs->mapaddr, KM_USER0); | 556 | kunmap(buf->page); |
539 | buf->len = PAGE_SIZE - cs->len; | 557 | buf->len = PAGE_SIZE - cs->len; |
540 | } | 558 | } |
541 | cs->currbuf = NULL; | 559 | cs->currbuf = NULL; |
542 | cs->mapaddr = NULL; | 560 | cs->mapaddr = NULL; |
543 | } else if (cs->mapaddr) { | 561 | } else if (cs->mapaddr) { |
544 | kunmap_atomic(cs->mapaddr, KM_USER0); | 562 | kunmap(cs->pg); |
545 | if (cs->write) { | 563 | if (cs->write) { |
546 | flush_dcache_page(cs->pg); | 564 | flush_dcache_page(cs->pg); |
547 | set_page_dirty_lock(cs->pg); | 565 | set_page_dirty_lock(cs->pg); |
@@ -572,7 +590,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) | |||
572 | 590 | ||
573 | BUG_ON(!cs->nr_segs); | 591 | BUG_ON(!cs->nr_segs); |
574 | cs->currbuf = buf; | 592 | cs->currbuf = buf; |
575 | cs->mapaddr = buf->ops->map(cs->pipe, buf, 1); | 593 | cs->mapaddr = buf->ops->map(cs->pipe, buf, 0); |
576 | cs->len = buf->len; | 594 | cs->len = buf->len; |
577 | cs->buf = cs->mapaddr + buf->offset; | 595 | cs->buf = cs->mapaddr + buf->offset; |
578 | cs->pipebufs++; | 596 | cs->pipebufs++; |
@@ -592,7 +610,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) | |||
592 | buf->len = 0; | 610 | buf->len = 0; |
593 | 611 | ||
594 | cs->currbuf = buf; | 612 | cs->currbuf = buf; |
595 | cs->mapaddr = kmap_atomic(page, KM_USER0); | 613 | cs->mapaddr = kmap(page); |
596 | cs->buf = cs->mapaddr; | 614 | cs->buf = cs->mapaddr; |
597 | cs->len = PAGE_SIZE; | 615 | cs->len = PAGE_SIZE; |
598 | cs->pipebufs++; | 616 | cs->pipebufs++; |
@@ -611,7 +629,7 @@ static int fuse_copy_fill(struct fuse_copy_state *cs) | |||
611 | return err; | 629 | return err; |
612 | BUG_ON(err != 1); | 630 | BUG_ON(err != 1); |
613 | offset = cs->addr % PAGE_SIZE; | 631 | offset = cs->addr % PAGE_SIZE; |
614 | cs->mapaddr = kmap_atomic(cs->pg, KM_USER0); | 632 | cs->mapaddr = kmap(cs->pg); |
615 | cs->buf = cs->mapaddr + offset; | 633 | cs->buf = cs->mapaddr + offset; |
616 | cs->len = min(PAGE_SIZE - offset, cs->seglen); | 634 | cs->len = min(PAGE_SIZE - offset, cs->seglen); |
617 | cs->seglen -= cs->len; | 635 | cs->seglen -= cs->len; |
@@ -1231,6 +1249,199 @@ err: | |||
1231 | return err; | 1249 | return err; |
1232 | } | 1250 | } |
1233 | 1251 | ||
1252 | static int fuse_notify_store(struct fuse_conn *fc, unsigned int size, | ||
1253 | struct fuse_copy_state *cs) | ||
1254 | { | ||
1255 | struct fuse_notify_store_out outarg; | ||
1256 | struct inode *inode; | ||
1257 | struct address_space *mapping; | ||
1258 | u64 nodeid; | ||
1259 | int err; | ||
1260 | pgoff_t index; | ||
1261 | unsigned int offset; | ||
1262 | unsigned int num; | ||
1263 | loff_t file_size; | ||
1264 | loff_t end; | ||
1265 | |||
1266 | err = -EINVAL; | ||
1267 | if (size < sizeof(outarg)) | ||
1268 | goto out_finish; | ||
1269 | |||
1270 | err = fuse_copy_one(cs, &outarg, sizeof(outarg)); | ||
1271 | if (err) | ||
1272 | goto out_finish; | ||
1273 | |||
1274 | err = -EINVAL; | ||
1275 | if (size - sizeof(outarg) != outarg.size) | ||
1276 | goto out_finish; | ||
1277 | |||
1278 | nodeid = outarg.nodeid; | ||
1279 | |||
1280 | down_read(&fc->killsb); | ||
1281 | |||
1282 | err = -ENOENT; | ||
1283 | if (!fc->sb) | ||
1284 | goto out_up_killsb; | ||
1285 | |||
1286 | inode = ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid); | ||
1287 | if (!inode) | ||
1288 | goto out_up_killsb; | ||
1289 | |||
1290 | mapping = inode->i_mapping; | ||
1291 | index = outarg.offset >> PAGE_CACHE_SHIFT; | ||
1292 | offset = outarg.offset & ~PAGE_CACHE_MASK; | ||
1293 | file_size = i_size_read(inode); | ||
1294 | end = outarg.offset + outarg.size; | ||
1295 | if (end > file_size) { | ||
1296 | file_size = end; | ||
1297 | fuse_write_update_size(inode, file_size); | ||
1298 | } | ||
1299 | |||
1300 | num = outarg.size; | ||
1301 | while (num) { | ||
1302 | struct page *page; | ||
1303 | unsigned int this_num; | ||
1304 | |||
1305 | err = -ENOMEM; | ||
1306 | page = find_or_create_page(mapping, index, | ||
1307 | mapping_gfp_mask(mapping)); | ||
1308 | if (!page) | ||
1309 | goto out_iput; | ||
1310 | |||
1311 | this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset); | ||
1312 | err = fuse_copy_page(cs, &page, offset, this_num, 0); | ||
1313 | if (!err && offset == 0 && (num != 0 || file_size == end)) | ||
1314 | SetPageUptodate(page); | ||
1315 | unlock_page(page); | ||
1316 | page_cache_release(page); | ||
1317 | |||
1318 | if (err) | ||
1319 | goto out_iput; | ||
1320 | |||
1321 | num -= this_num; | ||
1322 | offset = 0; | ||
1323 | index++; | ||
1324 | } | ||
1325 | |||
1326 | err = 0; | ||
1327 | |||
1328 | out_iput: | ||
1329 | iput(inode); | ||
1330 | out_up_killsb: | ||
1331 | up_read(&fc->killsb); | ||
1332 | out_finish: | ||
1333 | fuse_copy_finish(cs); | ||
1334 | return err; | ||
1335 | } | ||
1336 | |||
1337 | static void fuse_retrieve_end(struct fuse_conn *fc, struct fuse_req *req) | ||
1338 | { | ||
1339 | int i; | ||
1340 | |||
1341 | for (i = 0; i < req->num_pages; i++) { | ||
1342 | struct page *page = req->pages[i]; | ||
1343 | page_cache_release(page); | ||
1344 | } | ||
1345 | } | ||
1346 | |||
1347 | static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, | ||
1348 | struct fuse_notify_retrieve_out *outarg) | ||
1349 | { | ||
1350 | int err; | ||
1351 | struct address_space *mapping = inode->i_mapping; | ||
1352 | struct fuse_req *req; | ||
1353 | pgoff_t index; | ||
1354 | loff_t file_size; | ||
1355 | unsigned int num; | ||
1356 | unsigned int offset; | ||
1357 | size_t total_len; | ||
1358 | |||
1359 | req = fuse_get_req(fc); | ||
1360 | if (IS_ERR(req)) | ||
1361 | return PTR_ERR(req); | ||
1362 | |||
1363 | offset = outarg->offset & ~PAGE_CACHE_MASK; | ||
1364 | |||
1365 | req->in.h.opcode = FUSE_NOTIFY_REPLY; | ||
1366 | req->in.h.nodeid = outarg->nodeid; | ||
1367 | req->in.numargs = 2; | ||
1368 | req->in.argpages = 1; | ||
1369 | req->page_offset = offset; | ||
1370 | req->end = fuse_retrieve_end; | ||
1371 | |||
1372 | index = outarg->offset >> PAGE_CACHE_SHIFT; | ||
1373 | file_size = i_size_read(inode); | ||
1374 | num = outarg->size; | ||
1375 | if (outarg->offset > file_size) | ||
1376 | num = 0; | ||
1377 | else if (outarg->offset + num > file_size) | ||
1378 | num = file_size - outarg->offset; | ||
1379 | |||
1380 | while (num) { | ||
1381 | struct page *page; | ||
1382 | unsigned int this_num; | ||
1383 | |||
1384 | page = find_get_page(mapping, index); | ||
1385 | if (!page) | ||
1386 | break; | ||
1387 | |||
1388 | this_num = min_t(unsigned, num, PAGE_CACHE_SIZE - offset); | ||
1389 | req->pages[req->num_pages] = page; | ||
1390 | req->num_pages++; | ||
1391 | |||
1392 | num -= this_num; | ||
1393 | total_len += this_num; | ||
1394 | } | ||
1395 | req->misc.retrieve_in.offset = outarg->offset; | ||
1396 | req->misc.retrieve_in.size = total_len; | ||
1397 | req->in.args[0].size = sizeof(req->misc.retrieve_in); | ||
1398 | req->in.args[0].value = &req->misc.retrieve_in; | ||
1399 | req->in.args[1].size = total_len; | ||
1400 | |||
1401 | err = fuse_request_send_notify_reply(fc, req, outarg->notify_unique); | ||
1402 | if (err) | ||
1403 | fuse_retrieve_end(fc, req); | ||
1404 | |||
1405 | return err; | ||
1406 | } | ||
1407 | |||
1408 | static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size, | ||
1409 | struct fuse_copy_state *cs) | ||
1410 | { | ||
1411 | struct fuse_notify_retrieve_out outarg; | ||
1412 | struct inode *inode; | ||
1413 | int err; | ||
1414 | |||
1415 | err = -EINVAL; | ||
1416 | if (size != sizeof(outarg)) | ||
1417 | goto copy_finish; | ||
1418 | |||
1419 | err = fuse_copy_one(cs, &outarg, sizeof(outarg)); | ||
1420 | if (err) | ||
1421 | goto copy_finish; | ||
1422 | |||
1423 | fuse_copy_finish(cs); | ||
1424 | |||
1425 | down_read(&fc->killsb); | ||
1426 | err = -ENOENT; | ||
1427 | if (fc->sb) { | ||
1428 | u64 nodeid = outarg.nodeid; | ||
1429 | |||
1430 | inode = ilookup5(fc->sb, nodeid, fuse_inode_eq, &nodeid); | ||
1431 | if (inode) { | ||
1432 | err = fuse_retrieve(fc, inode, &outarg); | ||
1433 | iput(inode); | ||
1434 | } | ||
1435 | } | ||
1436 | up_read(&fc->killsb); | ||
1437 | |||
1438 | return err; | ||
1439 | |||
1440 | copy_finish: | ||
1441 | fuse_copy_finish(cs); | ||
1442 | return err; | ||
1443 | } | ||
1444 | |||
1234 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, | 1445 | static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, |
1235 | unsigned int size, struct fuse_copy_state *cs) | 1446 | unsigned int size, struct fuse_copy_state *cs) |
1236 | { | 1447 | { |
@@ -1244,6 +1455,12 @@ static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code, | |||
1244 | case FUSE_NOTIFY_INVAL_ENTRY: | 1455 | case FUSE_NOTIFY_INVAL_ENTRY: |
1245 | return fuse_notify_inval_entry(fc, size, cs); | 1456 | return fuse_notify_inval_entry(fc, size, cs); |
1246 | 1457 | ||
1458 | case FUSE_NOTIFY_STORE: | ||
1459 | return fuse_notify_store(fc, size, cs); | ||
1460 | |||
1461 | case FUSE_NOTIFY_RETRIEVE: | ||
1462 | return fuse_notify_retrieve(fc, size, cs); | ||
1463 | |||
1247 | default: | 1464 | default: |
1248 | fuse_copy_finish(cs); | 1465 | fuse_copy_finish(cs); |
1249 | return -EINVAL; | 1466 | return -EINVAL; |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 3cdc5f78a406..431be0795b6b 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -1016,7 +1016,7 @@ static int fuse_permission(struct inode *inode, int mask) | |||
1016 | exist. So if permissions are revoked this won't be | 1016 | exist. So if permissions are revoked this won't be |
1017 | noticed immediately, only after the attribute | 1017 | noticed immediately, only after the attribute |
1018 | timeout has expired */ | 1018 | timeout has expired */ |
1019 | } else if (mask & MAY_ACCESS) { | 1019 | } else if (mask & (MAY_ACCESS | MAY_CHDIR)) { |
1020 | err = fuse_access(inode, mask); | 1020 | err = fuse_access(inode, mask); |
1021 | } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { | 1021 | } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { |
1022 | if (!(inode->i_mode & S_IXUGO)) { | 1022 | if (!(inode->i_mode & S_IXUGO)) { |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index ada0adeb3bb5..147c1f71bdb9 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -706,7 +706,7 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping, | |||
706 | return 0; | 706 | return 0; |
707 | } | 707 | } |
708 | 708 | ||
709 | static void fuse_write_update_size(struct inode *inode, loff_t pos) | 709 | void fuse_write_update_size(struct inode *inode, loff_t pos) |
710 | { | 710 | { |
711 | struct fuse_conn *fc = get_fuse_conn(inode); | 711 | struct fuse_conn *fc = get_fuse_conn(inode); |
712 | struct fuse_inode *fi = get_fuse_inode(inode); | 712 | struct fuse_inode *fi = get_fuse_inode(inode); |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 8f309f04064e..57d4a3a0f102 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -272,6 +272,7 @@ struct fuse_req { | |||
272 | struct fuse_write_in in; | 272 | struct fuse_write_in in; |
273 | struct fuse_write_out out; | 273 | struct fuse_write_out out; |
274 | } write; | 274 | } write; |
275 | struct fuse_notify_retrieve_in retrieve_in; | ||
275 | struct fuse_lk_in lk_in; | 276 | struct fuse_lk_in lk_in; |
276 | } misc; | 277 | } misc; |
277 | 278 | ||
@@ -748,4 +749,6 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
748 | unsigned fuse_file_poll(struct file *file, poll_table *wait); | 749 | unsigned fuse_file_poll(struct file *file, poll_table *wait); |
749 | int fuse_dev_release(struct inode *inode, struct file *file); | 750 | int fuse_dev_release(struct inode *inode, struct file *file); |
750 | 751 | ||
752 | void fuse_write_update_size(struct inode *inode, loff_t pos); | ||
753 | |||
751 | #endif /* _FS_FUSE_I_H */ | 754 | #endif /* _FS_FUSE_I_H */ |
diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig index a47b43107112..cc9665522148 100644 --- a/fs/gfs2/Kconfig +++ b/fs/gfs2/Kconfig | |||
@@ -7,7 +7,6 @@ config GFS2_FS | |||
7 | select IP_SCTP if DLM_SCTP | 7 | select IP_SCTP if DLM_SCTP |
8 | select FS_POSIX_ACL | 8 | select FS_POSIX_ACL |
9 | select CRC32 | 9 | select CRC32 |
10 | select SLOW_WORK | ||
11 | select QUOTACTL | 10 | select QUOTACTL |
12 | help | 11 | help |
13 | A cluster filesystem. | 12 | A cluster filesystem. |
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 9f8b52500d63..5e96cbd8a454 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
@@ -136,10 +136,7 @@ static int gfs2_writeback_writepage(struct page *page, | |||
136 | if (ret <= 0) | 136 | if (ret <= 0) |
137 | return ret; | 137 | return ret; |
138 | 138 | ||
139 | ret = mpage_writepage(page, gfs2_get_block_noalloc, wbc); | 139 | return nobh_writepage(page, gfs2_get_block_noalloc, wbc); |
140 | if (ret == -EAGAIN) | ||
141 | ret = block_write_full_page(page, gfs2_get_block_noalloc, wbc); | ||
142 | return ret; | ||
143 | } | 140 | } |
144 | 141 | ||
145 | /** | 142 | /** |
@@ -637,9 +634,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, | |||
637 | } | 634 | } |
638 | } | 635 | } |
639 | 636 | ||
640 | error = gfs2_write_alloc_required(ip, pos, len, &alloc_required); | 637 | alloc_required = gfs2_write_alloc_required(ip, pos, len); |
641 | if (error) | ||
642 | goto out_unlock; | ||
643 | 638 | ||
644 | if (alloc_required || gfs2_is_jdata(ip)) | 639 | if (alloc_required || gfs2_is_jdata(ip)) |
645 | gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks); | 640 | gfs2_write_calc_reserv(ip, len, &data_blocks, &ind_blocks); |
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 4a48c0f4b402..6f482809d1a3 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -1040,7 +1040,8 @@ static int trunc_start(struct gfs2_inode *ip, u64 size) | |||
1040 | goto out; | 1040 | goto out; |
1041 | 1041 | ||
1042 | if (gfs2_is_stuffed(ip)) { | 1042 | if (gfs2_is_stuffed(ip)) { |
1043 | u64 dsize = size + sizeof(struct gfs2_inode); | 1043 | u64 dsize = size + sizeof(struct gfs2_dinode); |
1044 | ip->i_disksize = size; | ||
1044 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; | 1045 | ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME; |
1045 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 1046 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
1046 | gfs2_dinode_out(ip, dibh->b_data); | 1047 | gfs2_dinode_out(ip, dibh->b_data); |
@@ -1243,13 +1244,12 @@ int gfs2_file_dealloc(struct gfs2_inode *ip) | |||
1243 | * @ip: the file being written to | 1244 | * @ip: the file being written to |
1244 | * @offset: the offset to write to | 1245 | * @offset: the offset to write to |
1245 | * @len: the number of bytes being written | 1246 | * @len: the number of bytes being written |
1246 | * @alloc_required: set to 1 if an alloc is required, 0 otherwise | ||
1247 | * | 1247 | * |
1248 | * Returns: errno | 1248 | * Returns: 1 if an alloc is required, 0 otherwise |
1249 | */ | 1249 | */ |
1250 | 1250 | ||
1251 | int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | 1251 | int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, |
1252 | unsigned int len, int *alloc_required) | 1252 | unsigned int len) |
1253 | { | 1253 | { |
1254 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1254 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1255 | struct buffer_head bh; | 1255 | struct buffer_head bh; |
@@ -1257,26 +1257,23 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
1257 | u64 lblock, lblock_stop, size; | 1257 | u64 lblock, lblock_stop, size; |
1258 | u64 end_of_file; | 1258 | u64 end_of_file; |
1259 | 1259 | ||
1260 | *alloc_required = 0; | ||
1261 | |||
1262 | if (!len) | 1260 | if (!len) |
1263 | return 0; | 1261 | return 0; |
1264 | 1262 | ||
1265 | if (gfs2_is_stuffed(ip)) { | 1263 | if (gfs2_is_stuffed(ip)) { |
1266 | if (offset + len > | 1264 | if (offset + len > |
1267 | sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) | 1265 | sdp->sd_sb.sb_bsize - sizeof(struct gfs2_dinode)) |
1268 | *alloc_required = 1; | 1266 | return 1; |
1269 | return 0; | 1267 | return 0; |
1270 | } | 1268 | } |
1271 | 1269 | ||
1272 | *alloc_required = 1; | ||
1273 | shift = sdp->sd_sb.sb_bsize_shift; | 1270 | shift = sdp->sd_sb.sb_bsize_shift; |
1274 | BUG_ON(gfs2_is_dir(ip)); | 1271 | BUG_ON(gfs2_is_dir(ip)); |
1275 | end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift; | 1272 | end_of_file = (ip->i_disksize + sdp->sd_sb.sb_bsize - 1) >> shift; |
1276 | lblock = offset >> shift; | 1273 | lblock = offset >> shift; |
1277 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; | 1274 | lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift; |
1278 | if (lblock_stop > end_of_file) | 1275 | if (lblock_stop > end_of_file) |
1279 | return 0; | 1276 | return 1; |
1280 | 1277 | ||
1281 | size = (lblock_stop - lblock) << shift; | 1278 | size = (lblock_stop - lblock) << shift; |
1282 | do { | 1279 | do { |
@@ -1284,12 +1281,11 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | |||
1284 | bh.b_size = size; | 1281 | bh.b_size = size; |
1285 | gfs2_block_map(&ip->i_inode, lblock, &bh, 0); | 1282 | gfs2_block_map(&ip->i_inode, lblock, &bh, 0); |
1286 | if (!buffer_mapped(&bh)) | 1283 | if (!buffer_mapped(&bh)) |
1287 | return 0; | 1284 | return 1; |
1288 | size -= bh.b_size; | 1285 | size -= bh.b_size; |
1289 | lblock += (bh.b_size >> ip->i_inode.i_blkbits); | 1286 | lblock += (bh.b_size >> ip->i_inode.i_blkbits); |
1290 | } while(size > 0); | 1287 | } while(size > 0); |
1291 | 1288 | ||
1292 | *alloc_required = 0; | ||
1293 | return 0; | 1289 | return 0; |
1294 | } | 1290 | } |
1295 | 1291 | ||
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h index c983177e05ac..a20a5213135a 100644 --- a/fs/gfs2/bmap.h +++ b/fs/gfs2/bmap.h | |||
@@ -52,6 +52,6 @@ int gfs2_truncatei(struct gfs2_inode *ip, u64 size); | |||
52 | int gfs2_truncatei_resume(struct gfs2_inode *ip); | 52 | int gfs2_truncatei_resume(struct gfs2_inode *ip); |
53 | int gfs2_file_dealloc(struct gfs2_inode *ip); | 53 | int gfs2_file_dealloc(struct gfs2_inode *ip); |
54 | int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, | 54 | int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, |
55 | unsigned int len, int *alloc_required); | 55 | unsigned int len); |
56 | 56 | ||
57 | #endif /* __BMAP_DOT_H__ */ | 57 | #endif /* __BMAP_DOT_H__ */ |
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 8295c5b5d4a9..b9dd88a78dd4 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c | |||
@@ -392,7 +392,7 @@ static int gfs2_dirent_find_space(const struct gfs2_dirent *dent, | |||
392 | unsigned totlen = be16_to_cpu(dent->de_rec_len); | 392 | unsigned totlen = be16_to_cpu(dent->de_rec_len); |
393 | 393 | ||
394 | if (gfs2_dirent_sentinel(dent)) | 394 | if (gfs2_dirent_sentinel(dent)) |
395 | actual = GFS2_DIRENT_SIZE(0); | 395 | actual = 0; |
396 | if (totlen - actual >= required) | 396 | if (totlen - actual >= required) |
397 | return 1; | 397 | return 1; |
398 | return 0; | 398 | return 0; |
@@ -955,7 +955,12 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) | |||
955 | /* Change the pointers. | 955 | /* Change the pointers. |
956 | Don't bother distinguishing stuffed from non-stuffed. | 956 | Don't bother distinguishing stuffed from non-stuffed. |
957 | This code is complicated enough already. */ | 957 | This code is complicated enough already. */ |
958 | lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS | __GFP_NOFAIL); | 958 | lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS); |
959 | if (!lp) { | ||
960 | error = -ENOMEM; | ||
961 | goto fail_brelse; | ||
962 | } | ||
963 | |||
959 | /* Change the pointers */ | 964 | /* Change the pointers */ |
960 | for (x = 0; x < half_len; x++) | 965 | for (x = 0; x < half_len; x++) |
961 | lp[x] = cpu_to_be64(bn); | 966 | lp[x] = cpu_to_be64(bn); |
@@ -1063,7 +1068,9 @@ static int dir_double_exhash(struct gfs2_inode *dip) | |||
1063 | 1068 | ||
1064 | /* Allocate both the "from" and "to" buffers in one big chunk */ | 1069 | /* Allocate both the "from" and "to" buffers in one big chunk */ |
1065 | 1070 | ||
1066 | buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS | __GFP_NOFAIL); | 1071 | buf = kcalloc(3, sdp->sd_hash_bsize, GFP_NOFS); |
1072 | if (!buf) | ||
1073 | return -ENOMEM; | ||
1067 | 1074 | ||
1068 | for (block = dip->i_disksize >> sdp->sd_hash_bsize_shift; block--;) { | 1075 | for (block = dip->i_disksize >> sdp->sd_hash_bsize_shift; block--;) { |
1069 | error = gfs2_dir_read_data(dip, (char *)buf, | 1076 | error = gfs2_dir_read_data(dip, (char *)buf, |
@@ -1231,6 +1238,25 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, | |||
1231 | return 0; | 1238 | return 0; |
1232 | } | 1239 | } |
1233 | 1240 | ||
1241 | static void *gfs2_alloc_sort_buffer(unsigned size) | ||
1242 | { | ||
1243 | void *ptr = NULL; | ||
1244 | |||
1245 | if (size < KMALLOC_MAX_SIZE) | ||
1246 | ptr = kmalloc(size, GFP_NOFS | __GFP_NOWARN); | ||
1247 | if (!ptr) | ||
1248 | ptr = __vmalloc(size, GFP_NOFS, PAGE_KERNEL); | ||
1249 | return ptr; | ||
1250 | } | ||
1251 | |||
1252 | static void gfs2_free_sort_buffer(void *ptr) | ||
1253 | { | ||
1254 | if (is_vmalloc_addr(ptr)) | ||
1255 | vfree(ptr); | ||
1256 | else | ||
1257 | kfree(ptr); | ||
1258 | } | ||
1259 | |||
1234 | static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | 1260 | static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, |
1235 | filldir_t filldir, int *copied, unsigned *depth, | 1261 | filldir_t filldir, int *copied, unsigned *depth, |
1236 | u64 leaf_no) | 1262 | u64 leaf_no) |
@@ -1271,7 +1297,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
1271 | * 99 is the maximum number of entries that can fit in a single | 1297 | * 99 is the maximum number of entries that can fit in a single |
1272 | * leaf block. | 1298 | * leaf block. |
1273 | */ | 1299 | */ |
1274 | larr = vmalloc((leaves + entries + 99) * sizeof(void *)); | 1300 | larr = gfs2_alloc_sort_buffer((leaves + entries + 99) * sizeof(void *)); |
1275 | if (!larr) | 1301 | if (!larr) |
1276 | goto out; | 1302 | goto out; |
1277 | darr = (const struct gfs2_dirent **)(larr + leaves); | 1303 | darr = (const struct gfs2_dirent **)(larr + leaves); |
@@ -1282,7 +1308,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
1282 | do { | 1308 | do { |
1283 | error = get_leaf(ip, lfn, &bh); | 1309 | error = get_leaf(ip, lfn, &bh); |
1284 | if (error) | 1310 | if (error) |
1285 | goto out_kfree; | 1311 | goto out_free; |
1286 | lf = (struct gfs2_leaf *)bh->b_data; | 1312 | lf = (struct gfs2_leaf *)bh->b_data; |
1287 | lfn = be64_to_cpu(lf->lf_next); | 1313 | lfn = be64_to_cpu(lf->lf_next); |
1288 | if (lf->lf_entries) { | 1314 | if (lf->lf_entries) { |
@@ -1291,7 +1317,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
1291 | gfs2_dirent_gather, NULL, &g); | 1317 | gfs2_dirent_gather, NULL, &g); |
1292 | error = PTR_ERR(dent); | 1318 | error = PTR_ERR(dent); |
1293 | if (IS_ERR(dent)) | 1319 | if (IS_ERR(dent)) |
1294 | goto out_kfree; | 1320 | goto out_free; |
1295 | if (entries2 != g.offset) { | 1321 | if (entries2 != g.offset) { |
1296 | fs_warn(sdp, "Number of entries corrupt in dir " | 1322 | fs_warn(sdp, "Number of entries corrupt in dir " |
1297 | "leaf %llu, entries2 (%u) != " | 1323 | "leaf %llu, entries2 (%u) != " |
@@ -1300,7 +1326,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
1300 | entries2, g.offset); | 1326 | entries2, g.offset); |
1301 | 1327 | ||
1302 | error = -EIO; | 1328 | error = -EIO; |
1303 | goto out_kfree; | 1329 | goto out_free; |
1304 | } | 1330 | } |
1305 | error = 0; | 1331 | error = 0; |
1306 | larr[leaf++] = bh; | 1332 | larr[leaf++] = bh; |
@@ -1312,10 +1338,10 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, | |||
1312 | BUG_ON(entries2 != entries); | 1338 | BUG_ON(entries2 != entries); |
1313 | error = do_filldir_main(ip, offset, opaque, filldir, darr, | 1339 | error = do_filldir_main(ip, offset, opaque, filldir, darr, |
1314 | entries, copied); | 1340 | entries, copied); |
1315 | out_kfree: | 1341 | out_free: |
1316 | for(i = 0; i < leaf; i++) | 1342 | for(i = 0; i < leaf; i++) |
1317 | brelse(larr[i]); | 1343 | brelse(larr[i]); |
1318 | vfree(larr); | 1344 | gfs2_free_sort_buffer(larr); |
1319 | out: | 1345 | out: |
1320 | return error; | 1346 | return error; |
1321 | } | 1347 | } |
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index ed9a94f0ef15..4edd662c8232 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c | |||
@@ -351,7 +351,6 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
351 | unsigned long last_index; | 351 | unsigned long last_index; |
352 | u64 pos = page->index << PAGE_CACHE_SHIFT; | 352 | u64 pos = page->index << PAGE_CACHE_SHIFT; |
353 | unsigned int data_blocks, ind_blocks, rblocks; | 353 | unsigned int data_blocks, ind_blocks, rblocks; |
354 | int alloc_required = 0; | ||
355 | struct gfs2_holder gh; | 354 | struct gfs2_holder gh; |
356 | struct gfs2_alloc *al; | 355 | struct gfs2_alloc *al; |
357 | int ret; | 356 | int ret; |
@@ -364,8 +363,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
364 | set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); | 363 | set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); |
365 | set_bit(GIF_SW_PAGED, &ip->i_flags); | 364 | set_bit(GIF_SW_PAGED, &ip->i_flags); |
366 | 365 | ||
367 | ret = gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE, &alloc_required); | 366 | if (!gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE)) |
368 | if (ret || !alloc_required) | ||
369 | goto out_unlock; | 367 | goto out_unlock; |
370 | ret = -ENOMEM; | 368 | ret = -ENOMEM; |
371 | al = gfs2_alloc_get(ip); | 369 | al = gfs2_alloc_get(ip); |
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index ddcdbf493536..9adf8f924e08 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -328,6 +328,30 @@ static void gfs2_holder_wake(struct gfs2_holder *gh) | |||
328 | } | 328 | } |
329 | 329 | ||
330 | /** | 330 | /** |
331 | * do_error - Something unexpected has happened during a lock request | ||
332 | * | ||
333 | */ | ||
334 | |||
335 | static inline void do_error(struct gfs2_glock *gl, const int ret) | ||
336 | { | ||
337 | struct gfs2_holder *gh, *tmp; | ||
338 | |||
339 | list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) { | ||
340 | if (test_bit(HIF_HOLDER, &gh->gh_iflags)) | ||
341 | continue; | ||
342 | if (ret & LM_OUT_ERROR) | ||
343 | gh->gh_error = -EIO; | ||
344 | else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) | ||
345 | gh->gh_error = GLR_TRYFAILED; | ||
346 | else | ||
347 | continue; | ||
348 | list_del_init(&gh->gh_list); | ||
349 | trace_gfs2_glock_queue(gh, 0); | ||
350 | gfs2_holder_wake(gh); | ||
351 | } | ||
352 | } | ||
353 | |||
354 | /** | ||
331 | * do_promote - promote as many requests as possible on the current queue | 355 | * do_promote - promote as many requests as possible on the current queue |
332 | * @gl: The glock | 356 | * @gl: The glock |
333 | * | 357 | * |
@@ -375,36 +399,13 @@ restart: | |||
375 | } | 399 | } |
376 | if (gh->gh_list.prev == &gl->gl_holders) | 400 | if (gh->gh_list.prev == &gl->gl_holders) |
377 | return 1; | 401 | return 1; |
402 | do_error(gl, 0); | ||
378 | break; | 403 | break; |
379 | } | 404 | } |
380 | return 0; | 405 | return 0; |
381 | } | 406 | } |
382 | 407 | ||
383 | /** | 408 | /** |
384 | * do_error - Something unexpected has happened during a lock request | ||
385 | * | ||
386 | */ | ||
387 | |||
388 | static inline void do_error(struct gfs2_glock *gl, const int ret) | ||
389 | { | ||
390 | struct gfs2_holder *gh, *tmp; | ||
391 | |||
392 | list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) { | ||
393 | if (test_bit(HIF_HOLDER, &gh->gh_iflags)) | ||
394 | continue; | ||
395 | if (ret & LM_OUT_ERROR) | ||
396 | gh->gh_error = -EIO; | ||
397 | else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB)) | ||
398 | gh->gh_error = GLR_TRYFAILED; | ||
399 | else | ||
400 | continue; | ||
401 | list_del_init(&gh->gh_list); | ||
402 | trace_gfs2_glock_queue(gh, 0); | ||
403 | gfs2_holder_wake(gh); | ||
404 | } | ||
405 | } | ||
406 | |||
407 | /** | ||
408 | * find_first_waiter - find the first gh that's waiting for the glock | 409 | * find_first_waiter - find the first gh that's waiting for the glock |
409 | * @gl: the glock | 410 | * @gl: the glock |
410 | */ | 411 | */ |
@@ -1062,6 +1063,9 @@ int gfs2_glock_nq(struct gfs2_holder *gh) | |||
1062 | 1063 | ||
1063 | spin_lock(&gl->gl_spin); | 1064 | spin_lock(&gl->gl_spin); |
1064 | add_to_queue(gh); | 1065 | add_to_queue(gh); |
1066 | if ((LM_FLAG_NOEXP & gh->gh_flags) && | ||
1067 | test_and_clear_bit(GLF_FROZEN, &gl->gl_flags)) | ||
1068 | set_bit(GLF_REPLY_PENDING, &gl->gl_flags); | ||
1065 | run_queue(gl, 1); | 1069 | run_queue(gl, 1); |
1066 | spin_unlock(&gl->gl_spin); | 1070 | spin_unlock(&gl->gl_spin); |
1067 | 1071 | ||
@@ -1319,6 +1323,36 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) | |||
1319 | } | 1323 | } |
1320 | 1324 | ||
1321 | /** | 1325 | /** |
1326 | * gfs2_should_freeze - Figure out if glock should be frozen | ||
1327 | * @gl: The glock in question | ||
1328 | * | ||
1329 | * Glocks are not frozen if (a) the result of the dlm operation is | ||
1330 | * an error, (b) the locking operation was an unlock operation or | ||
1331 | * (c) if there is a "noexp" flagged request anywhere in the queue | ||
1332 | * | ||
1333 | * Returns: 1 if freezing should occur, 0 otherwise | ||
1334 | */ | ||
1335 | |||
1336 | static int gfs2_should_freeze(const struct gfs2_glock *gl) | ||
1337 | { | ||
1338 | const struct gfs2_holder *gh; | ||
1339 | |||
1340 | if (gl->gl_reply & ~LM_OUT_ST_MASK) | ||
1341 | return 0; | ||
1342 | if (gl->gl_target == LM_ST_UNLOCKED) | ||
1343 | return 0; | ||
1344 | |||
1345 | list_for_each_entry(gh, &gl->gl_holders, gh_list) { | ||
1346 | if (test_bit(HIF_HOLDER, &gh->gh_iflags)) | ||
1347 | continue; | ||
1348 | if (LM_FLAG_NOEXP & gh->gh_flags) | ||
1349 | return 0; | ||
1350 | } | ||
1351 | |||
1352 | return 1; | ||
1353 | } | ||
1354 | |||
1355 | /** | ||
1322 | * gfs2_glock_complete - Callback used by locking | 1356 | * gfs2_glock_complete - Callback used by locking |
1323 | * @gl: Pointer to the glock | 1357 | * @gl: Pointer to the glock |
1324 | * @ret: The return value from the dlm | 1358 | * @ret: The return value from the dlm |
@@ -1328,18 +1362,17 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state) | |||
1328 | void gfs2_glock_complete(struct gfs2_glock *gl, int ret) | 1362 | void gfs2_glock_complete(struct gfs2_glock *gl, int ret) |
1329 | { | 1363 | { |
1330 | struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; | 1364 | struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; |
1365 | |||
1331 | gl->gl_reply = ret; | 1366 | gl->gl_reply = ret; |
1367 | |||
1332 | if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) { | 1368 | if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) { |
1333 | struct gfs2_holder *gh; | ||
1334 | spin_lock(&gl->gl_spin); | 1369 | spin_lock(&gl->gl_spin); |
1335 | gh = find_first_waiter(gl); | 1370 | if (gfs2_should_freeze(gl)) { |
1336 | if ((!(gh && (gh->gh_flags & LM_FLAG_NOEXP)) && | ||
1337 | (gl->gl_target != LM_ST_UNLOCKED)) || | ||
1338 | ((ret & ~LM_OUT_ST_MASK) != 0)) | ||
1339 | set_bit(GLF_FROZEN, &gl->gl_flags); | 1371 | set_bit(GLF_FROZEN, &gl->gl_flags); |
1340 | spin_unlock(&gl->gl_spin); | 1372 | spin_unlock(&gl->gl_spin); |
1341 | if (test_bit(GLF_FROZEN, &gl->gl_flags)) | ||
1342 | return; | 1373 | return; |
1374 | } | ||
1375 | spin_unlock(&gl->gl_spin); | ||
1343 | } | 1376 | } |
1344 | set_bit(GLF_REPLY_PENDING, &gl->gl_flags); | 1377 | set_bit(GLF_REPLY_PENDING, &gl->gl_flags); |
1345 | gfs2_glock_hold(gl); | 1378 | gfs2_glock_hold(gl); |
@@ -1348,7 +1381,7 @@ void gfs2_glock_complete(struct gfs2_glock *gl, int ret) | |||
1348 | } | 1381 | } |
1349 | 1382 | ||
1350 | 1383 | ||
1351 | static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask) | 1384 | static int gfs2_shrink_glock_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
1352 | { | 1385 | { |
1353 | struct gfs2_glock *gl; | 1386 | struct gfs2_glock *gl; |
1354 | int may_demote; | 1387 | int may_demote; |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index b5d7363b22da..fdbf4b366fa5 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -12,7 +12,6 @@ | |||
12 | 12 | ||
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/workqueue.h> | 14 | #include <linux/workqueue.h> |
15 | #include <linux/slow-work.h> | ||
16 | #include <linux/dlm.h> | 15 | #include <linux/dlm.h> |
17 | #include <linux/buffer_head.h> | 16 | #include <linux/buffer_head.h> |
18 | 17 | ||
@@ -383,7 +382,7 @@ struct gfs2_journal_extent { | |||
383 | struct gfs2_jdesc { | 382 | struct gfs2_jdesc { |
384 | struct list_head jd_list; | 383 | struct list_head jd_list; |
385 | struct list_head extent_list; | 384 | struct list_head extent_list; |
386 | struct slow_work jd_work; | 385 | struct work_struct jd_work; |
387 | struct inode *jd_inode; | 386 | struct inode *jd_inode; |
388 | unsigned long jd_flags; | 387 | unsigned long jd_flags; |
389 | #define JDF_RECOVERY 1 | 388 | #define JDF_RECOVERY 1 |
@@ -460,6 +459,7 @@ enum { | |||
460 | SDF_NOBARRIERS = 3, | 459 | SDF_NOBARRIERS = 3, |
461 | SDF_NORECOVERY = 4, | 460 | SDF_NORECOVERY = 4, |
462 | SDF_DEMOTE = 5, | 461 | SDF_DEMOTE = 5, |
462 | SDF_NOJOURNALID = 6, | ||
463 | }; | 463 | }; |
464 | 464 | ||
465 | #define GFS2_FSNAME_LEN 256 | 465 | #define GFS2_FSNAME_LEN 256 |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index b5612cbb62a5..f03afd9c44bc 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -169,7 +169,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, | |||
169 | { | 169 | { |
170 | struct inode *inode; | 170 | struct inode *inode; |
171 | struct gfs2_inode *ip; | 171 | struct gfs2_inode *ip; |
172 | struct gfs2_glock *io_gl; | 172 | struct gfs2_glock *io_gl = NULL; |
173 | int error; | 173 | int error; |
174 | 174 | ||
175 | inode = gfs2_iget(sb, no_addr); | 175 | inode = gfs2_iget(sb, no_addr); |
@@ -198,6 +198,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, | |||
198 | ip->i_iopen_gh.gh_gl->gl_object = ip; | 198 | ip->i_iopen_gh.gh_gl->gl_object = ip; |
199 | 199 | ||
200 | gfs2_glock_put(io_gl); | 200 | gfs2_glock_put(io_gl); |
201 | io_gl = NULL; | ||
201 | 202 | ||
202 | if ((type == DT_UNKNOWN) && (no_formal_ino == 0)) | 203 | if ((type == DT_UNKNOWN) && (no_formal_ino == 0)) |
203 | goto gfs2_nfsbypass; | 204 | goto gfs2_nfsbypass; |
@@ -228,7 +229,8 @@ gfs2_nfsbypass: | |||
228 | fail_glock: | 229 | fail_glock: |
229 | gfs2_glock_dq(&ip->i_iopen_gh); | 230 | gfs2_glock_dq(&ip->i_iopen_gh); |
230 | fail_iopen: | 231 | fail_iopen: |
231 | gfs2_glock_put(io_gl); | 232 | if (io_gl) |
233 | gfs2_glock_put(io_gl); | ||
232 | fail_put: | 234 | fail_put: |
233 | if (inode->i_state & I_NEW) | 235 | if (inode->i_state & I_NEW) |
234 | ip->i_gl->gl_object = NULL; | 236 | ip->i_gl->gl_object = NULL; |
@@ -256,7 +258,7 @@ void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr) | |||
256 | { | 258 | { |
257 | struct gfs2_sbd *sdp; | 259 | struct gfs2_sbd *sdp; |
258 | struct gfs2_inode *ip; | 260 | struct gfs2_inode *ip; |
259 | struct gfs2_glock *io_gl; | 261 | struct gfs2_glock *io_gl = NULL; |
260 | int error; | 262 | int error; |
261 | struct gfs2_holder gh; | 263 | struct gfs2_holder gh; |
262 | struct inode *inode; | 264 | struct inode *inode; |
@@ -293,6 +295,7 @@ void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr) | |||
293 | 295 | ||
294 | ip->i_iopen_gh.gh_gl->gl_object = ip; | 296 | ip->i_iopen_gh.gh_gl->gl_object = ip; |
295 | gfs2_glock_put(io_gl); | 297 | gfs2_glock_put(io_gl); |
298 | io_gl = NULL; | ||
296 | 299 | ||
297 | inode->i_mode = DT2IF(DT_UNKNOWN); | 300 | inode->i_mode = DT2IF(DT_UNKNOWN); |
298 | 301 | ||
@@ -319,7 +322,8 @@ void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr) | |||
319 | fail_glock: | 322 | fail_glock: |
320 | gfs2_glock_dq(&ip->i_iopen_gh); | 323 | gfs2_glock_dq(&ip->i_iopen_gh); |
321 | fail_iopen: | 324 | fail_iopen: |
322 | gfs2_glock_put(io_gl); | 325 | if (io_gl) |
326 | gfs2_glock_put(io_gl); | ||
323 | fail_put: | 327 | fail_put: |
324 | ip->i_gl->gl_object = NULL; | 328 | ip->i_gl->gl_object = NULL; |
325 | gfs2_glock_put(ip->i_gl); | 329 | gfs2_glock_put(ip->i_gl); |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index fb2a5f93b7c3..b1e9630eb46a 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/gfs2_ondisk.h> | 16 | #include <linux/gfs2_ondisk.h> |
17 | #include <asm/atomic.h> | 17 | #include <asm/atomic.h> |
18 | #include <linux/slow-work.h> | ||
19 | 18 | ||
20 | #include "gfs2.h" | 19 | #include "gfs2.h" |
21 | #include "incore.h" | 20 | #include "incore.h" |
@@ -24,6 +23,7 @@ | |||
24 | #include "util.h" | 23 | #include "util.h" |
25 | #include "glock.h" | 24 | #include "glock.h" |
26 | #include "quota.h" | 25 | #include "quota.h" |
26 | #include "recovery.h" | ||
27 | 27 | ||
28 | static struct shrinker qd_shrinker = { | 28 | static struct shrinker qd_shrinker = { |
29 | .shrink = gfs2_shrink_qd_memory, | 29 | .shrink = gfs2_shrink_qd_memory, |
@@ -138,9 +138,11 @@ static int __init init_gfs2_fs(void) | |||
138 | if (error) | 138 | if (error) |
139 | goto fail_unregister; | 139 | goto fail_unregister; |
140 | 140 | ||
141 | error = slow_work_register_user(THIS_MODULE); | 141 | error = -ENOMEM; |
142 | if (error) | 142 | gfs_recovery_wq = alloc_workqueue("gfs_recovery", |
143 | goto fail_slow; | 143 | WQ_NON_REENTRANT | WQ_RESCUER, 0); |
144 | if (!gfs_recovery_wq) | ||
145 | goto fail_wq; | ||
144 | 146 | ||
145 | gfs2_register_debugfs(); | 147 | gfs2_register_debugfs(); |
146 | 148 | ||
@@ -148,7 +150,7 @@ static int __init init_gfs2_fs(void) | |||
148 | 150 | ||
149 | return 0; | 151 | return 0; |
150 | 152 | ||
151 | fail_slow: | 153 | fail_wq: |
152 | unregister_filesystem(&gfs2meta_fs_type); | 154 | unregister_filesystem(&gfs2meta_fs_type); |
153 | fail_unregister: | 155 | fail_unregister: |
154 | unregister_filesystem(&gfs2_fs_type); | 156 | unregister_filesystem(&gfs2_fs_type); |
@@ -190,7 +192,7 @@ static void __exit exit_gfs2_fs(void) | |||
190 | gfs2_unregister_debugfs(); | 192 | gfs2_unregister_debugfs(); |
191 | unregister_filesystem(&gfs2_fs_type); | 193 | unregister_filesystem(&gfs2_fs_type); |
192 | unregister_filesystem(&gfs2meta_fs_type); | 194 | unregister_filesystem(&gfs2meta_fs_type); |
193 | slow_work_unregister_user(THIS_MODULE); | 195 | destroy_workqueue(gfs_recovery_wq); |
194 | 196 | ||
195 | kmem_cache_destroy(gfs2_quotad_cachep); | 197 | kmem_cache_destroy(gfs2_quotad_cachep); |
196 | kmem_cache_destroy(gfs2_rgrpd_cachep); | 198 | kmem_cache_destroy(gfs2_rgrpd_cachep); |
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 3593b3a7290e..4f44bdeb2f03 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/namei.h> | 17 | #include <linux/namei.h> |
18 | #include <linux/mount.h> | 18 | #include <linux/mount.h> |
19 | #include <linux/gfs2_ondisk.h> | 19 | #include <linux/gfs2_ondisk.h> |
20 | #include <linux/slow-work.h> | ||
21 | #include <linux/quotaops.h> | 20 | #include <linux/quotaops.h> |
22 | 21 | ||
23 | #include "gfs2.h" | 22 | #include "gfs2.h" |
@@ -76,7 +75,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) | |||
76 | 75 | ||
77 | sb->s_fs_info = sdp; | 76 | sb->s_fs_info = sdp; |
78 | sdp->sd_vfs = sb; | 77 | sdp->sd_vfs = sb; |
79 | 78 | set_bit(SDF_NOJOURNALID, &sdp->sd_flags); | |
80 | gfs2_tune_init(&sdp->sd_tune); | 79 | gfs2_tune_init(&sdp->sd_tune); |
81 | 80 | ||
82 | init_waitqueue_head(&sdp->sd_glock_wait); | 81 | init_waitqueue_head(&sdp->sd_glock_wait); |
@@ -673,7 +672,7 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) | |||
673 | break; | 672 | break; |
674 | 673 | ||
675 | INIT_LIST_HEAD(&jd->extent_list); | 674 | INIT_LIST_HEAD(&jd->extent_list); |
676 | slow_work_init(&jd->jd_work, &gfs2_recover_ops); | 675 | INIT_WORK(&jd->jd_work, gfs2_recover_func); |
677 | jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1); | 676 | jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1); |
678 | if (!jd->jd_inode || IS_ERR(jd->jd_inode)) { | 677 | if (!jd->jd_inode || IS_ERR(jd->jd_inode)) { |
679 | if (!jd->jd_inode) | 678 | if (!jd->jd_inode) |
@@ -782,7 +781,8 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) | |||
782 | if (sdp->sd_lockstruct.ls_first) { | 781 | if (sdp->sd_lockstruct.ls_first) { |
783 | unsigned int x; | 782 | unsigned int x; |
784 | for (x = 0; x < sdp->sd_journals; x++) { | 783 | for (x = 0; x < sdp->sd_journals; x++) { |
785 | error = gfs2_recover_journal(gfs2_jdesc_find(sdp, x)); | 784 | error = gfs2_recover_journal(gfs2_jdesc_find(sdp, x), |
785 | true); | ||
786 | if (error) { | 786 | if (error) { |
787 | fs_err(sdp, "error recovering journal %u: %d\n", | 787 | fs_err(sdp, "error recovering journal %u: %d\n", |
788 | x, error); | 788 | x, error); |
@@ -792,7 +792,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) | |||
792 | 792 | ||
793 | gfs2_others_may_mount(sdp); | 793 | gfs2_others_may_mount(sdp); |
794 | } else if (!sdp->sd_args.ar_spectator) { | 794 | } else if (!sdp->sd_args.ar_spectator) { |
795 | error = gfs2_recover_journal(sdp->sd_jdesc); | 795 | error = gfs2_recover_journal(sdp->sd_jdesc, true); |
796 | if (error) { | 796 | if (error) { |
797 | fs_err(sdp, "error recovering my journal: %d\n", error); | 797 | fs_err(sdp, "error recovering my journal: %d\n", error); |
798 | goto fail_jinode_gh; | 798 | goto fail_jinode_gh; |
@@ -1050,7 +1050,8 @@ static int gfs2_lm_mount(struct gfs2_sbd *sdp, int silent) | |||
1050 | ret = match_int(&tmp[0], &option); | 1050 | ret = match_int(&tmp[0], &option); |
1051 | if (ret || option < 0) | 1051 | if (ret || option < 0) |
1052 | goto hostdata_error; | 1052 | goto hostdata_error; |
1053 | ls->ls_jid = option; | 1053 | if (test_and_clear_bit(SDF_NOJOURNALID, &sdp->sd_flags)) |
1054 | ls->ls_jid = option; | ||
1054 | break; | 1055 | break; |
1055 | case Opt_id: | 1056 | case Opt_id: |
1056 | /* Obsolete, but left for backward compat purposes */ | 1057 | /* Obsolete, but left for backward compat purposes */ |
@@ -1102,6 +1103,24 @@ void gfs2_lm_unmount(struct gfs2_sbd *sdp) | |||
1102 | lm->lm_unmount(sdp); | 1103 | lm->lm_unmount(sdp); |
1103 | } | 1104 | } |
1104 | 1105 | ||
1106 | static int gfs2_journalid_wait(void *word) | ||
1107 | { | ||
1108 | if (signal_pending(current)) | ||
1109 | return -EINTR; | ||
1110 | schedule(); | ||
1111 | return 0; | ||
1112 | } | ||
1113 | |||
1114 | static int wait_on_journal(struct gfs2_sbd *sdp) | ||
1115 | { | ||
1116 | if (sdp->sd_args.ar_spectator) | ||
1117 | return 0; | ||
1118 | if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) | ||
1119 | return 0; | ||
1120 | |||
1121 | return wait_on_bit(&sdp->sd_flags, SDF_NOJOURNALID, gfs2_journalid_wait, TASK_INTERRUPTIBLE); | ||
1122 | } | ||
1123 | |||
1105 | void gfs2_online_uevent(struct gfs2_sbd *sdp) | 1124 | void gfs2_online_uevent(struct gfs2_sbd *sdp) |
1106 | { | 1125 | { |
1107 | struct super_block *sb = sdp->sd_vfs; | 1126 | struct super_block *sb = sdp->sd_vfs; |
@@ -1194,6 +1213,10 @@ static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent | |||
1194 | if (error) | 1213 | if (error) |
1195 | goto fail_locking; | 1214 | goto fail_locking; |
1196 | 1215 | ||
1216 | error = wait_on_journal(sdp); | ||
1217 | if (error) | ||
1218 | goto fail_sb; | ||
1219 | |||
1197 | error = init_inodes(sdp, DO); | 1220 | error = init_inodes(sdp, DO); |
1198 | if (error) | 1221 | if (error) |
1199 | goto fail_sb; | 1222 | goto fail_sb; |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 49667d68769e..1bc6b5695e6d 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
@@ -77,7 +77,7 @@ static LIST_HEAD(qd_lru_list); | |||
77 | static atomic_t qd_lru_count = ATOMIC_INIT(0); | 77 | static atomic_t qd_lru_count = ATOMIC_INIT(0); |
78 | static DEFINE_SPINLOCK(qd_lru_lock); | 78 | static DEFINE_SPINLOCK(qd_lru_lock); |
79 | 79 | ||
80 | int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask) | 80 | int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
81 | { | 81 | { |
82 | struct gfs2_quota_data *qd; | 82 | struct gfs2_quota_data *qd; |
83 | struct gfs2_sbd *sdp; | 83 | struct gfs2_sbd *sdp; |
@@ -694,10 +694,8 @@ get_a_page: | |||
694 | if (!buffer_mapped(bh)) | 694 | if (!buffer_mapped(bh)) |
695 | goto unlock_out; | 695 | goto unlock_out; |
696 | /* If it's a newly allocated disk block for quota, zero it */ | 696 | /* If it's a newly allocated disk block for quota, zero it */ |
697 | if (buffer_new(bh)) { | 697 | if (buffer_new(bh)) |
698 | memset(bh->b_data, 0, bh->b_size); | 698 | zero_user(page, pos - blocksize, bh->b_size); |
699 | set_buffer_uptodate(bh); | ||
700 | } | ||
701 | } | 699 | } |
702 | 700 | ||
703 | if (PageUptodate(page)) | 701 | if (PageUptodate(page)) |
@@ -723,7 +721,7 @@ get_a_page: | |||
723 | 721 | ||
724 | /* If quota straddles page boundary, we need to update the rest of the | 722 | /* If quota straddles page boundary, we need to update the rest of the |
725 | * quota at the beginning of the next page */ | 723 | * quota at the beginning of the next page */ |
726 | if (offset != 0) { /* first page, offset is closer to PAGE_CACHE_SIZE */ | 724 | if ((offset + sizeof(struct gfs2_quota)) > PAGE_CACHE_SIZE) { |
727 | ptr = ptr + nbytes; | 725 | ptr = ptr + nbytes; |
728 | nbytes = sizeof(struct gfs2_quota) - nbytes; | 726 | nbytes = sizeof(struct gfs2_quota) - nbytes; |
729 | offset = 0; | 727 | offset = 0; |
@@ -789,15 +787,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda) | |||
789 | goto out; | 787 | goto out; |
790 | 788 | ||
791 | for (x = 0; x < num_qd; x++) { | 789 | for (x = 0; x < num_qd; x++) { |
792 | int alloc_required; | ||
793 | |||
794 | offset = qd2offset(qda[x]); | 790 | offset = qd2offset(qda[x]); |
795 | error = gfs2_write_alloc_required(ip, offset, | 791 | if (gfs2_write_alloc_required(ip, offset, |
796 | sizeof(struct gfs2_quota), | 792 | sizeof(struct gfs2_quota))) |
797 | &alloc_required); | ||
798 | if (error) | ||
799 | goto out_gunlock; | ||
800 | if (alloc_required) | ||
801 | nalloc++; | 793 | nalloc++; |
802 | } | 794 | } |
803 | 795 | ||
@@ -1457,10 +1449,10 @@ static int gfs2_quota_get_xstate(struct super_block *sb, | |||
1457 | 1449 | ||
1458 | switch (sdp->sd_args.ar_quota) { | 1450 | switch (sdp->sd_args.ar_quota) { |
1459 | case GFS2_QUOTA_ON: | 1451 | case GFS2_QUOTA_ON: |
1460 | fqs->qs_flags |= (XFS_QUOTA_UDQ_ENFD | XFS_QUOTA_GDQ_ENFD); | 1452 | fqs->qs_flags |= (FS_QUOTA_UDQ_ENFD | FS_QUOTA_GDQ_ENFD); |
1461 | /*FALLTHRU*/ | 1453 | /*FALLTHRU*/ |
1462 | case GFS2_QUOTA_ACCOUNT: | 1454 | case GFS2_QUOTA_ACCOUNT: |
1463 | fqs->qs_flags |= (XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_GDQ_ACCT); | 1455 | fqs->qs_flags |= (FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT); |
1464 | break; | 1456 | break; |
1465 | case GFS2_QUOTA_OFF: | 1457 | case GFS2_QUOTA_OFF: |
1466 | break; | 1458 | break; |
@@ -1506,7 +1498,7 @@ static int gfs2_get_dqblk(struct super_block *sb, int type, qid_t id, | |||
1506 | 1498 | ||
1507 | qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; | 1499 | qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; |
1508 | fdq->d_version = FS_DQUOT_VERSION; | 1500 | fdq->d_version = FS_DQUOT_VERSION; |
1509 | fdq->d_flags = (type == QUOTA_USER) ? XFS_USER_QUOTA : XFS_GROUP_QUOTA; | 1501 | fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA; |
1510 | fdq->d_id = id; | 1502 | fdq->d_id = id; |
1511 | fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit); | 1503 | fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit); |
1512 | fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn); | 1504 | fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn); |
@@ -1541,12 +1533,12 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id, | |||
1541 | switch(type) { | 1533 | switch(type) { |
1542 | case USRQUOTA: | 1534 | case USRQUOTA: |
1543 | type = QUOTA_USER; | 1535 | type = QUOTA_USER; |
1544 | if (fdq->d_flags != XFS_USER_QUOTA) | 1536 | if (fdq->d_flags != FS_USER_QUOTA) |
1545 | return -EINVAL; | 1537 | return -EINVAL; |
1546 | break; | 1538 | break; |
1547 | case GRPQUOTA: | 1539 | case GRPQUOTA: |
1548 | type = QUOTA_GROUP; | 1540 | type = QUOTA_GROUP; |
1549 | if (fdq->d_flags != XFS_GROUP_QUOTA) | 1541 | if (fdq->d_flags != FS_GROUP_QUOTA) |
1550 | return -EINVAL; | 1542 | return -EINVAL; |
1551 | break; | 1543 | break; |
1552 | default: | 1544 | default: |
@@ -1586,10 +1578,7 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id, | |||
1586 | goto out_i; | 1578 | goto out_i; |
1587 | 1579 | ||
1588 | offset = qd2offset(qd); | 1580 | offset = qd2offset(qd); |
1589 | error = gfs2_write_alloc_required(ip, offset, sizeof(struct gfs2_quota), | 1581 | alloc_required = gfs2_write_alloc_required(ip, offset, sizeof(struct gfs2_quota)); |
1590 | &alloc_required); | ||
1591 | if (error) | ||
1592 | goto out_i; | ||
1593 | if (alloc_required) { | 1582 | if (alloc_required) { |
1594 | al = gfs2_alloc_get(ip); | 1583 | al = gfs2_alloc_get(ip); |
1595 | if (al == NULL) | 1584 | if (al == NULL) |
diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h index 195f60c8bd14..e7d236ca48bd 100644 --- a/fs/gfs2/quota.h +++ b/fs/gfs2/quota.h | |||
@@ -51,7 +51,7 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip) | |||
51 | return ret; | 51 | return ret; |
52 | } | 52 | } |
53 | 53 | ||
54 | extern int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask); | 54 | extern int gfs2_shrink_qd_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask); |
55 | extern const struct quotactl_ops gfs2_quotactl_ops; | 55 | extern const struct quotactl_ops gfs2_quotactl_ops; |
56 | 56 | ||
57 | #endif /* __QUOTA_DOT_H__ */ | 57 | #endif /* __QUOTA_DOT_H__ */ |
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 4b9bece3d437..f7f89a94a5a4 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/buffer_head.h> | 14 | #include <linux/buffer_head.h> |
15 | #include <linux/gfs2_ondisk.h> | 15 | #include <linux/gfs2_ondisk.h> |
16 | #include <linux/crc32.h> | 16 | #include <linux/crc32.h> |
17 | #include <linux/slow-work.h> | ||
18 | 17 | ||
19 | #include "gfs2.h" | 18 | #include "gfs2.h" |
20 | #include "incore.h" | 19 | #include "incore.h" |
@@ -28,6 +27,8 @@ | |||
28 | #include "util.h" | 27 | #include "util.h" |
29 | #include "dir.h" | 28 | #include "dir.h" |
30 | 29 | ||
30 | struct workqueue_struct *gfs_recovery_wq; | ||
31 | |||
31 | int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk, | 32 | int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk, |
32 | struct buffer_head **bh) | 33 | struct buffer_head **bh) |
33 | { | 34 | { |
@@ -443,23 +444,7 @@ static void gfs2_recovery_done(struct gfs2_sbd *sdp, unsigned int jid, | |||
443 | kobject_uevent_env(&sdp->sd_kobj, KOBJ_CHANGE, envp); | 444 | kobject_uevent_env(&sdp->sd_kobj, KOBJ_CHANGE, envp); |
444 | } | 445 | } |
445 | 446 | ||
446 | static int gfs2_recover_get_ref(struct slow_work *work) | 447 | void gfs2_recover_func(struct work_struct *work) |
447 | { | ||
448 | struct gfs2_jdesc *jd = container_of(work, struct gfs2_jdesc, jd_work); | ||
449 | if (test_and_set_bit(JDF_RECOVERY, &jd->jd_flags)) | ||
450 | return -EBUSY; | ||
451 | return 0; | ||
452 | } | ||
453 | |||
454 | static void gfs2_recover_put_ref(struct slow_work *work) | ||
455 | { | ||
456 | struct gfs2_jdesc *jd = container_of(work, struct gfs2_jdesc, jd_work); | ||
457 | clear_bit(JDF_RECOVERY, &jd->jd_flags); | ||
458 | smp_mb__after_clear_bit(); | ||
459 | wake_up_bit(&jd->jd_flags, JDF_RECOVERY); | ||
460 | } | ||
461 | |||
462 | static void gfs2_recover_work(struct slow_work *work) | ||
463 | { | 448 | { |
464 | struct gfs2_jdesc *jd = container_of(work, struct gfs2_jdesc, jd_work); | 449 | struct gfs2_jdesc *jd = container_of(work, struct gfs2_jdesc, jd_work); |
465 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); | 450 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); |
@@ -578,7 +563,7 @@ static void gfs2_recover_work(struct slow_work *work) | |||
578 | gfs2_glock_dq_uninit(&j_gh); | 563 | gfs2_glock_dq_uninit(&j_gh); |
579 | 564 | ||
580 | fs_info(sdp, "jid=%u: Done\n", jd->jd_jid); | 565 | fs_info(sdp, "jid=%u: Done\n", jd->jd_jid); |
581 | return; | 566 | goto done; |
582 | 567 | ||
583 | fail_gunlock_tr: | 568 | fail_gunlock_tr: |
584 | gfs2_glock_dq_uninit(&t_gh); | 569 | gfs2_glock_dq_uninit(&t_gh); |
@@ -590,32 +575,35 @@ fail_gunlock_j: | |||
590 | } | 575 | } |
591 | 576 | ||
592 | fs_info(sdp, "jid=%u: %s\n", jd->jd_jid, (error) ? "Failed" : "Done"); | 577 | fs_info(sdp, "jid=%u: %s\n", jd->jd_jid, (error) ? "Failed" : "Done"); |
593 | |||
594 | fail: | 578 | fail: |
595 | gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP); | 579 | gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_GAVEUP); |
580 | done: | ||
581 | clear_bit(JDF_RECOVERY, &jd->jd_flags); | ||
582 | smp_mb__after_clear_bit(); | ||
583 | wake_up_bit(&jd->jd_flags, JDF_RECOVERY); | ||
596 | } | 584 | } |
597 | 585 | ||
598 | struct slow_work_ops gfs2_recover_ops = { | ||
599 | .owner = THIS_MODULE, | ||
600 | .get_ref = gfs2_recover_get_ref, | ||
601 | .put_ref = gfs2_recover_put_ref, | ||
602 | .execute = gfs2_recover_work, | ||
603 | }; | ||
604 | |||
605 | |||
606 | static int gfs2_recovery_wait(void *word) | 586 | static int gfs2_recovery_wait(void *word) |
607 | { | 587 | { |
608 | schedule(); | 588 | schedule(); |
609 | return 0; | 589 | return 0; |
610 | } | 590 | } |
611 | 591 | ||
612 | int gfs2_recover_journal(struct gfs2_jdesc *jd) | 592 | int gfs2_recover_journal(struct gfs2_jdesc *jd, bool wait) |
613 | { | 593 | { |
614 | int rv; | 594 | int rv; |
615 | rv = slow_work_enqueue(&jd->jd_work); | 595 | |
616 | if (rv) | 596 | if (test_and_set_bit(JDF_RECOVERY, &jd->jd_flags)) |
617 | return rv; | 597 | return -EBUSY; |
618 | wait_on_bit(&jd->jd_flags, JDF_RECOVERY, gfs2_recovery_wait, TASK_UNINTERRUPTIBLE); | 598 | |
599 | /* we have JDF_RECOVERY, queue should always succeed */ | ||
600 | rv = queue_work(gfs_recovery_wq, &jd->jd_work); | ||
601 | BUG_ON(!rv); | ||
602 | |||
603 | if (wait) | ||
604 | wait_on_bit(&jd->jd_flags, JDF_RECOVERY, gfs2_recovery_wait, | ||
605 | TASK_UNINTERRUPTIBLE); | ||
606 | |||
619 | return 0; | 607 | return 0; |
620 | } | 608 | } |
621 | 609 | ||
diff --git a/fs/gfs2/recovery.h b/fs/gfs2/recovery.h index 1616ac22569a..2226136c7647 100644 --- a/fs/gfs2/recovery.h +++ b/fs/gfs2/recovery.h | |||
@@ -12,6 +12,8 @@ | |||
12 | 12 | ||
13 | #include "incore.h" | 13 | #include "incore.h" |
14 | 14 | ||
15 | extern struct workqueue_struct *gfs_recovery_wq; | ||
16 | |||
15 | static inline void gfs2_replay_incr_blk(struct gfs2_sbd *sdp, unsigned int *blk) | 17 | static inline void gfs2_replay_incr_blk(struct gfs2_sbd *sdp, unsigned int *blk) |
16 | { | 18 | { |
17 | if (++*blk == sdp->sd_jdesc->jd_blocks) | 19 | if (++*blk == sdp->sd_jdesc->jd_blocks) |
@@ -27,8 +29,8 @@ extern void gfs2_revoke_clean(struct gfs2_sbd *sdp); | |||
27 | 29 | ||
28 | extern int gfs2_find_jhead(struct gfs2_jdesc *jd, | 30 | extern int gfs2_find_jhead(struct gfs2_jdesc *jd, |
29 | struct gfs2_log_header_host *head); | 31 | struct gfs2_log_header_host *head); |
30 | extern int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd); | 32 | extern int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd, bool wait); |
31 | extern struct slow_work_ops gfs2_recover_ops; | 33 | extern void gfs2_recover_func(struct work_struct *work); |
32 | 34 | ||
33 | #endif /* __RECOVERY_DOT_H__ */ | 35 | #endif /* __RECOVERY_DOT_H__ */ |
34 | 36 | ||
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 4d1aad38f1b1..4140811a921c 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -342,8 +342,6 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd) | |||
342 | { | 342 | { |
343 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); | 343 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); |
344 | struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); | 344 | struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); |
345 | int ar; | ||
346 | int error; | ||
347 | 345 | ||
348 | if (ip->i_disksize < (8 << 20) || ip->i_disksize > (1 << 30) || | 346 | if (ip->i_disksize < (8 << 20) || ip->i_disksize > (1 << 30) || |
349 | (ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) { | 347 | (ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) { |
@@ -352,13 +350,12 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd) | |||
352 | } | 350 | } |
353 | jd->jd_blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift; | 351 | jd->jd_blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift; |
354 | 352 | ||
355 | error = gfs2_write_alloc_required(ip, 0, ip->i_disksize, &ar); | 353 | if (gfs2_write_alloc_required(ip, 0, ip->i_disksize)) { |
356 | if (!error && ar) { | ||
357 | gfs2_consist_inode(ip); | 354 | gfs2_consist_inode(ip); |
358 | error = -EIO; | 355 | return -EIO; |
359 | } | 356 | } |
360 | 357 | ||
361 | return error; | 358 | return 0; |
362 | } | 359 | } |
363 | 360 | ||
364 | /** | 361 | /** |
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 37f5393e68e6..ccacffd2faaa 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "quota.h" | 25 | #include "quota.h" |
26 | #include "util.h" | 26 | #include "util.h" |
27 | #include "glops.h" | 27 | #include "glops.h" |
28 | #include "recovery.h" | ||
28 | 29 | ||
29 | struct gfs2_attr { | 30 | struct gfs2_attr { |
30 | struct attribute attr; | 31 | struct attribute attr; |
@@ -325,6 +326,30 @@ static ssize_t lkfirst_show(struct gfs2_sbd *sdp, char *buf) | |||
325 | return sprintf(buf, "%d\n", ls->ls_first); | 326 | return sprintf(buf, "%d\n", ls->ls_first); |
326 | } | 327 | } |
327 | 328 | ||
329 | static ssize_t lkfirst_store(struct gfs2_sbd *sdp, const char *buf, size_t len) | ||
330 | { | ||
331 | unsigned first; | ||
332 | int rv; | ||
333 | |||
334 | rv = sscanf(buf, "%u", &first); | ||
335 | if (rv != 1 || first > 1) | ||
336 | return -EINVAL; | ||
337 | spin_lock(&sdp->sd_jindex_spin); | ||
338 | rv = -EBUSY; | ||
339 | if (test_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0) | ||
340 | goto out; | ||
341 | rv = -EINVAL; | ||
342 | if (sdp->sd_args.ar_spectator) | ||
343 | goto out; | ||
344 | if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) | ||
345 | goto out; | ||
346 | sdp->sd_lockstruct.ls_first = first; | ||
347 | rv = 0; | ||
348 | out: | ||
349 | spin_unlock(&sdp->sd_jindex_spin); | ||
350 | return rv ? rv : len; | ||
351 | } | ||
352 | |||
328 | static ssize_t first_done_show(struct gfs2_sbd *sdp, char *buf) | 353 | static ssize_t first_done_show(struct gfs2_sbd *sdp, char *buf) |
329 | { | 354 | { |
330 | struct lm_lockstruct *ls = &sdp->sd_lockstruct; | 355 | struct lm_lockstruct *ls = &sdp->sd_lockstruct; |
@@ -352,7 +377,7 @@ static ssize_t recover_store(struct gfs2_sbd *sdp, const char *buf, size_t len) | |||
352 | list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { | 377 | list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { |
353 | if (jd->jd_jid != jid) | 378 | if (jd->jd_jid != jid) |
354 | continue; | 379 | continue; |
355 | rv = slow_work_enqueue(&jd->jd_work); | 380 | rv = gfs2_recover_journal(jd, false); |
356 | break; | 381 | break; |
357 | } | 382 | } |
358 | out: | 383 | out: |
@@ -377,14 +402,41 @@ static ssize_t jid_show(struct gfs2_sbd *sdp, char *buf) | |||
377 | return sprintf(buf, "%u\n", sdp->sd_lockstruct.ls_jid); | 402 | return sprintf(buf, "%u\n", sdp->sd_lockstruct.ls_jid); |
378 | } | 403 | } |
379 | 404 | ||
405 | static ssize_t jid_store(struct gfs2_sbd *sdp, const char *buf, size_t len) | ||
406 | { | ||
407 | unsigned jid; | ||
408 | int rv; | ||
409 | |||
410 | rv = sscanf(buf, "%u", &jid); | ||
411 | if (rv != 1) | ||
412 | return -EINVAL; | ||
413 | |||
414 | spin_lock(&sdp->sd_jindex_spin); | ||
415 | rv = -EINVAL; | ||
416 | if (sdp->sd_args.ar_spectator) | ||
417 | goto out; | ||
418 | if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) | ||
419 | goto out; | ||
420 | rv = -EBUSY; | ||
421 | if (test_and_clear_bit(SDF_NOJOURNALID, &sdp->sd_flags) == 0) | ||
422 | goto out; | ||
423 | sdp->sd_lockstruct.ls_jid = jid; | ||
424 | smp_mb__after_clear_bit(); | ||
425 | wake_up_bit(&sdp->sd_flags, SDF_NOJOURNALID); | ||
426 | rv = 0; | ||
427 | out: | ||
428 | spin_unlock(&sdp->sd_jindex_spin); | ||
429 | return rv ? rv : len; | ||
430 | } | ||
431 | |||
380 | #define GDLM_ATTR(_name,_mode,_show,_store) \ | 432 | #define GDLM_ATTR(_name,_mode,_show,_store) \ |
381 | static struct gfs2_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store) | 433 | static struct gfs2_attr gdlm_attr_##_name = __ATTR(_name,_mode,_show,_store) |
382 | 434 | ||
383 | GDLM_ATTR(proto_name, 0444, proto_name_show, NULL); | 435 | GDLM_ATTR(proto_name, 0444, proto_name_show, NULL); |
384 | GDLM_ATTR(block, 0644, block_show, block_store); | 436 | GDLM_ATTR(block, 0644, block_show, block_store); |
385 | GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store); | 437 | GDLM_ATTR(withdraw, 0644, withdraw_show, withdraw_store); |
386 | GDLM_ATTR(jid, 0444, jid_show, NULL); | 438 | GDLM_ATTR(jid, 0644, jid_show, jid_store); |
387 | GDLM_ATTR(first, 0444, lkfirst_show, NULL); | 439 | GDLM_ATTR(first, 0644, lkfirst_show, lkfirst_store); |
388 | GDLM_ATTR(first_done, 0444, first_done_show, NULL); | 440 | GDLM_ATTR(first_done, 0444, first_done_show, NULL); |
389 | GDLM_ATTR(recover, 0600, NULL, recover_store); | 441 | GDLM_ATTR(recover, 0600, NULL, recover_store); |
390 | GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); | 442 | GDLM_ATTR(recover_done, 0444, recover_done_show, NULL); |
@@ -564,7 +616,7 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj, | |||
564 | 616 | ||
565 | add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name); | 617 | add_uevent_var(env, "LOCKTABLE=%s", sdp->sd_table_name); |
566 | add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); | 618 | add_uevent_var(env, "LOCKPROTO=%s", sdp->sd_proto_name); |
567 | if (!sdp->sd_args.ar_spectator) | 619 | if (!test_bit(SDF_NOJOURNALID, &sdp->sd_flags)) |
568 | add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid); | 620 | add_uevent_var(env, "JOURNALID=%u", sdp->sd_lockstruct.ls_jid); |
569 | if (gfs2_uuid_valid(uuid)) | 621 | if (gfs2_uuid_valid(uuid)) |
570 | add_uevent_var(env, "UUID=%pUB", uuid); | 622 | add_uevent_var(env, "UUID=%pUB", uuid); |
diff --git a/fs/inode.c b/fs/inode.c index 2bee20ae3d65..722860b323a9 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
@@ -512,7 +512,7 @@ static void prune_icache(int nr_to_scan) | |||
512 | * This function is passed the number of inodes to scan, and it returns the | 512 | * This function is passed the number of inodes to scan, and it returns the |
513 | * total number of remaining possibly-reclaimable inodes. | 513 | * total number of remaining possibly-reclaimable inodes. |
514 | */ | 514 | */ |
515 | static int shrink_icache_memory(int nr, gfp_t gfp_mask) | 515 | static int shrink_icache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
516 | { | 516 | { |
517 | if (nr) { | 517 | if (nr) { |
518 | /* | 518 | /* |
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 93d1e47647bd..f19ce94693d8 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -1281,13 +1281,9 @@ int journal_check_used_features (journal_t *journal, unsigned long compat, | |||
1281 | int journal_check_available_features (journal_t *journal, unsigned long compat, | 1281 | int journal_check_available_features (journal_t *journal, unsigned long compat, |
1282 | unsigned long ro, unsigned long incompat) | 1282 | unsigned long ro, unsigned long incompat) |
1283 | { | 1283 | { |
1284 | journal_superblock_t *sb; | ||
1285 | |||
1286 | if (!compat && !ro && !incompat) | 1284 | if (!compat && !ro && !incompat) |
1287 | return 1; | 1285 | return 1; |
1288 | 1286 | ||
1289 | sb = journal->j_superblock; | ||
1290 | |||
1291 | /* We can support any known requested features iff the | 1287 | /* We can support any known requested features iff the |
1292 | * superblock is in version 2. Otherwise we fail to support any | 1288 | * superblock is in version 2. Otherwise we fail to support any |
1293 | * extended sb features. */ | 1289 | * extended sb features. */ |
@@ -1481,7 +1477,6 @@ int journal_flush(journal_t *journal) | |||
1481 | 1477 | ||
1482 | int journal_wipe(journal_t *journal, int write) | 1478 | int journal_wipe(journal_t *journal, int write) |
1483 | { | 1479 | { |
1484 | journal_superblock_t *sb; | ||
1485 | int err = 0; | 1480 | int err = 0; |
1486 | 1481 | ||
1487 | J_ASSERT (!(journal->j_flags & JFS_LOADED)); | 1482 | J_ASSERT (!(journal->j_flags & JFS_LOADED)); |
@@ -1490,8 +1485,6 @@ int journal_wipe(journal_t *journal, int write) | |||
1490 | if (err) | 1485 | if (err) |
1491 | return err; | 1486 | return err; |
1492 | 1487 | ||
1493 | sb = journal->j_superblock; | ||
1494 | |||
1495 | if (!journal->j_tail) | 1488 | if (!journal->j_tail) |
1496 | goto no_recovery; | 1489 | goto no_recovery; |
1497 | 1490 | ||
diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c index 54c9bc9e1b17..81051dafebf5 100644 --- a/fs/jbd/recovery.c +++ b/fs/jbd/recovery.c | |||
@@ -283,12 +283,9 @@ int journal_recover(journal_t *journal) | |||
283 | int journal_skip_recovery(journal_t *journal) | 283 | int journal_skip_recovery(journal_t *journal) |
284 | { | 284 | { |
285 | int err; | 285 | int err; |
286 | journal_superblock_t * sb; | ||
287 | |||
288 | struct recovery_info info; | 286 | struct recovery_info info; |
289 | 287 | ||
290 | memset (&info, 0, sizeof(info)); | 288 | memset (&info, 0, sizeof(info)); |
291 | sb = journal->j_superblock; | ||
292 | 289 | ||
293 | err = do_one_pass(journal, &info, PASS_SCAN); | 290 | err = do_one_pass(journal, &info, PASS_SCAN); |
294 | 291 | ||
@@ -297,7 +294,8 @@ int journal_skip_recovery(journal_t *journal) | |||
297 | ++journal->j_transaction_sequence; | 294 | ++journal->j_transaction_sequence; |
298 | } else { | 295 | } else { |
299 | #ifdef CONFIG_JBD_DEBUG | 296 | #ifdef CONFIG_JBD_DEBUG |
300 | int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence); | 297 | int dropped = info.end_transaction - |
298 | be32_to_cpu(journal->j_superblock->s_sequence); | ||
301 | #endif | 299 | #endif |
302 | jbd_debug(1, | 300 | jbd_debug(1, |
303 | "JBD: ignoring %d transaction%s from the journal.\n", | 301 | "JBD: ignoring %d transaction%s from the journal.\n", |
@@ -321,11 +319,6 @@ static int do_one_pass(journal_t *journal, | |||
321 | unsigned int sequence; | 319 | unsigned int sequence; |
322 | int blocktype; | 320 | int blocktype; |
323 | 321 | ||
324 | /* Precompute the maximum metadata descriptors in a descriptor block */ | ||
325 | int MAX_BLOCKS_PER_DESC; | ||
326 | MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t)) | ||
327 | / sizeof(journal_block_tag_t)); | ||
328 | |||
329 | /* | 322 | /* |
330 | * First thing is to establish what we expect to find in the log | 323 | * First thing is to establish what we expect to find in the log |
331 | * (in terms of transaction IDs), and where (in terms of log | 324 | * (in terms of transaction IDs), and where (in terms of log |
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 076d1cc44f95..1c23a0f4e8a3 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -118,13 +118,13 @@ static int __try_to_free_cp_buf(struct journal_head *jh) | |||
118 | void __jbd2_log_wait_for_space(journal_t *journal) | 118 | void __jbd2_log_wait_for_space(journal_t *journal) |
119 | { | 119 | { |
120 | int nblocks, space_left; | 120 | int nblocks, space_left; |
121 | assert_spin_locked(&journal->j_state_lock); | 121 | /* assert_spin_locked(&journal->j_state_lock); */ |
122 | 122 | ||
123 | nblocks = jbd_space_needed(journal); | 123 | nblocks = jbd_space_needed(journal); |
124 | while (__jbd2_log_space_left(journal) < nblocks) { | 124 | while (__jbd2_log_space_left(journal) < nblocks) { |
125 | if (journal->j_flags & JBD2_ABORT) | 125 | if (journal->j_flags & JBD2_ABORT) |
126 | return; | 126 | return; |
127 | spin_unlock(&journal->j_state_lock); | 127 | write_unlock(&journal->j_state_lock); |
128 | mutex_lock(&journal->j_checkpoint_mutex); | 128 | mutex_lock(&journal->j_checkpoint_mutex); |
129 | 129 | ||
130 | /* | 130 | /* |
@@ -138,7 +138,7 @@ void __jbd2_log_wait_for_space(journal_t *journal) | |||
138 | * filesystem, so abort the journal and leave a stack | 138 | * filesystem, so abort the journal and leave a stack |
139 | * trace for forensic evidence. | 139 | * trace for forensic evidence. |
140 | */ | 140 | */ |
141 | spin_lock(&journal->j_state_lock); | 141 | write_lock(&journal->j_state_lock); |
142 | spin_lock(&journal->j_list_lock); | 142 | spin_lock(&journal->j_list_lock); |
143 | nblocks = jbd_space_needed(journal); | 143 | nblocks = jbd_space_needed(journal); |
144 | space_left = __jbd2_log_space_left(journal); | 144 | space_left = __jbd2_log_space_left(journal); |
@@ -149,7 +149,7 @@ void __jbd2_log_wait_for_space(journal_t *journal) | |||
149 | if (journal->j_committing_transaction) | 149 | if (journal->j_committing_transaction) |
150 | tid = journal->j_committing_transaction->t_tid; | 150 | tid = journal->j_committing_transaction->t_tid; |
151 | spin_unlock(&journal->j_list_lock); | 151 | spin_unlock(&journal->j_list_lock); |
152 | spin_unlock(&journal->j_state_lock); | 152 | write_unlock(&journal->j_state_lock); |
153 | if (chkpt) { | 153 | if (chkpt) { |
154 | jbd2_log_do_checkpoint(journal); | 154 | jbd2_log_do_checkpoint(journal); |
155 | } else if (jbd2_cleanup_journal_tail(journal) == 0) { | 155 | } else if (jbd2_cleanup_journal_tail(journal) == 0) { |
@@ -167,7 +167,7 @@ void __jbd2_log_wait_for_space(journal_t *journal) | |||
167 | WARN_ON(1); | 167 | WARN_ON(1); |
168 | jbd2_journal_abort(journal, 0); | 168 | jbd2_journal_abort(journal, 0); |
169 | } | 169 | } |
170 | spin_lock(&journal->j_state_lock); | 170 | write_lock(&journal->j_state_lock); |
171 | } else { | 171 | } else { |
172 | spin_unlock(&journal->j_list_lock); | 172 | spin_unlock(&journal->j_list_lock); |
173 | } | 173 | } |
@@ -474,7 +474,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
474 | * next transaction ID we will write, and where it will | 474 | * next transaction ID we will write, and where it will |
475 | * start. */ | 475 | * start. */ |
476 | 476 | ||
477 | spin_lock(&journal->j_state_lock); | 477 | write_lock(&journal->j_state_lock); |
478 | spin_lock(&journal->j_list_lock); | 478 | spin_lock(&journal->j_list_lock); |
479 | transaction = journal->j_checkpoint_transactions; | 479 | transaction = journal->j_checkpoint_transactions; |
480 | if (transaction) { | 480 | if (transaction) { |
@@ -496,7 +496,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
496 | /* If the oldest pinned transaction is at the tail of the log | 496 | /* If the oldest pinned transaction is at the tail of the log |
497 | already then there's not much we can do right now. */ | 497 | already then there's not much we can do right now. */ |
498 | if (journal->j_tail_sequence == first_tid) { | 498 | if (journal->j_tail_sequence == first_tid) { |
499 | spin_unlock(&journal->j_state_lock); | 499 | write_unlock(&journal->j_state_lock); |
500 | return 1; | 500 | return 1; |
501 | } | 501 | } |
502 | 502 | ||
@@ -516,7 +516,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
516 | journal->j_free += freed; | 516 | journal->j_free += freed; |
517 | journal->j_tail_sequence = first_tid; | 517 | journal->j_tail_sequence = first_tid; |
518 | journal->j_tail = blocknr; | 518 | journal->j_tail = blocknr; |
519 | spin_unlock(&journal->j_state_lock); | 519 | write_unlock(&journal->j_state_lock); |
520 | 520 | ||
521 | /* | 521 | /* |
522 | * If there is an external journal, we need to make sure that | 522 | * If there is an external journal, we need to make sure that |
@@ -775,7 +775,7 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact | |||
775 | J_ASSERT(transaction->t_log_list == NULL); | 775 | J_ASSERT(transaction->t_log_list == NULL); |
776 | J_ASSERT(transaction->t_checkpoint_list == NULL); | 776 | J_ASSERT(transaction->t_checkpoint_list == NULL); |
777 | J_ASSERT(transaction->t_checkpoint_io_list == NULL); | 777 | J_ASSERT(transaction->t_checkpoint_io_list == NULL); |
778 | J_ASSERT(transaction->t_updates == 0); | 778 | J_ASSERT(atomic_read(&transaction->t_updates) == 0); |
779 | J_ASSERT(journal->j_committing_transaction != transaction); | 779 | J_ASSERT(journal->j_committing_transaction != transaction); |
780 | J_ASSERT(journal->j_running_transaction != transaction); | 780 | J_ASSERT(journal->j_running_transaction != transaction); |
781 | 781 | ||
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 75716d3d2be0..f52e5e8049f1 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -150,11 +150,11 @@ static int journal_submit_commit_record(journal_t *journal, | |||
150 | */ | 150 | */ |
151 | if (ret == -EOPNOTSUPP && barrier_done) { | 151 | if (ret == -EOPNOTSUPP && barrier_done) { |
152 | printk(KERN_WARNING | 152 | printk(KERN_WARNING |
153 | "JBD: barrier-based sync failed on %s - " | 153 | "JBD2: Disabling barriers on %s, " |
154 | "disabling barriers\n", journal->j_devname); | 154 | "not supported by device\n", journal->j_devname); |
155 | spin_lock(&journal->j_state_lock); | 155 | write_lock(&journal->j_state_lock); |
156 | journal->j_flags &= ~JBD2_BARRIER; | 156 | journal->j_flags &= ~JBD2_BARRIER; |
157 | spin_unlock(&journal->j_state_lock); | 157 | write_unlock(&journal->j_state_lock); |
158 | 158 | ||
159 | /* And try again, without the barrier */ | 159 | /* And try again, without the barrier */ |
160 | lock_buffer(bh); | 160 | lock_buffer(bh); |
@@ -180,11 +180,11 @@ retry: | |||
180 | wait_on_buffer(bh); | 180 | wait_on_buffer(bh); |
181 | if (buffer_eopnotsupp(bh) && (journal->j_flags & JBD2_BARRIER)) { | 181 | if (buffer_eopnotsupp(bh) && (journal->j_flags & JBD2_BARRIER)) { |
182 | printk(KERN_WARNING | 182 | printk(KERN_WARNING |
183 | "JBD2: wait_on_commit_record: sync failed on %s - " | 183 | "JBD2: %s: disabling barries on %s - not supported " |
184 | "disabling barriers\n", journal->j_devname); | 184 | "by device\n", __func__, journal->j_devname); |
185 | spin_lock(&journal->j_state_lock); | 185 | write_lock(&journal->j_state_lock); |
186 | journal->j_flags &= ~JBD2_BARRIER; | 186 | journal->j_flags &= ~JBD2_BARRIER; |
187 | spin_unlock(&journal->j_state_lock); | 187 | write_unlock(&journal->j_state_lock); |
188 | 188 | ||
189 | lock_buffer(bh); | 189 | lock_buffer(bh); |
190 | clear_buffer_dirty(bh); | 190 | clear_buffer_dirty(bh); |
@@ -400,7 +400,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
400 | jbd_debug(1, "JBD: starting commit of transaction %d\n", | 400 | jbd_debug(1, "JBD: starting commit of transaction %d\n", |
401 | commit_transaction->t_tid); | 401 | commit_transaction->t_tid); |
402 | 402 | ||
403 | spin_lock(&journal->j_state_lock); | 403 | write_lock(&journal->j_state_lock); |
404 | commit_transaction->t_state = T_LOCKED; | 404 | commit_transaction->t_state = T_LOCKED; |
405 | 405 | ||
406 | /* | 406 | /* |
@@ -417,23 +417,23 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
417 | stats.run.rs_locked); | 417 | stats.run.rs_locked); |
418 | 418 | ||
419 | spin_lock(&commit_transaction->t_handle_lock); | 419 | spin_lock(&commit_transaction->t_handle_lock); |
420 | while (commit_transaction->t_updates) { | 420 | while (atomic_read(&commit_transaction->t_updates)) { |
421 | DEFINE_WAIT(wait); | 421 | DEFINE_WAIT(wait); |
422 | 422 | ||
423 | prepare_to_wait(&journal->j_wait_updates, &wait, | 423 | prepare_to_wait(&journal->j_wait_updates, &wait, |
424 | TASK_UNINTERRUPTIBLE); | 424 | TASK_UNINTERRUPTIBLE); |
425 | if (commit_transaction->t_updates) { | 425 | if (atomic_read(&commit_transaction->t_updates)) { |
426 | spin_unlock(&commit_transaction->t_handle_lock); | 426 | spin_unlock(&commit_transaction->t_handle_lock); |
427 | spin_unlock(&journal->j_state_lock); | 427 | write_unlock(&journal->j_state_lock); |
428 | schedule(); | 428 | schedule(); |
429 | spin_lock(&journal->j_state_lock); | 429 | write_lock(&journal->j_state_lock); |
430 | spin_lock(&commit_transaction->t_handle_lock); | 430 | spin_lock(&commit_transaction->t_handle_lock); |
431 | } | 431 | } |
432 | finish_wait(&journal->j_wait_updates, &wait); | 432 | finish_wait(&journal->j_wait_updates, &wait); |
433 | } | 433 | } |
434 | spin_unlock(&commit_transaction->t_handle_lock); | 434 | spin_unlock(&commit_transaction->t_handle_lock); |
435 | 435 | ||
436 | J_ASSERT (commit_transaction->t_outstanding_credits <= | 436 | J_ASSERT (atomic_read(&commit_transaction->t_outstanding_credits) <= |
437 | journal->j_max_transaction_buffers); | 437 | journal->j_max_transaction_buffers); |
438 | 438 | ||
439 | /* | 439 | /* |
@@ -497,7 +497,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
497 | start_time = ktime_get(); | 497 | start_time = ktime_get(); |
498 | commit_transaction->t_log_start = journal->j_head; | 498 | commit_transaction->t_log_start = journal->j_head; |
499 | wake_up(&journal->j_wait_transaction_locked); | 499 | wake_up(&journal->j_wait_transaction_locked); |
500 | spin_unlock(&journal->j_state_lock); | 500 | write_unlock(&journal->j_state_lock); |
501 | 501 | ||
502 | jbd_debug (3, "JBD: commit phase 2\n"); | 502 | jbd_debug (3, "JBD: commit phase 2\n"); |
503 | 503 | ||
@@ -519,19 +519,20 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
519 | * transaction! Now comes the tricky part: we need to write out | 519 | * transaction! Now comes the tricky part: we need to write out |
520 | * metadata. Loop over the transaction's entire buffer list: | 520 | * metadata. Loop over the transaction's entire buffer list: |
521 | */ | 521 | */ |
522 | spin_lock(&journal->j_state_lock); | 522 | write_lock(&journal->j_state_lock); |
523 | commit_transaction->t_state = T_COMMIT; | 523 | commit_transaction->t_state = T_COMMIT; |
524 | spin_unlock(&journal->j_state_lock); | 524 | write_unlock(&journal->j_state_lock); |
525 | 525 | ||
526 | trace_jbd2_commit_logging(journal, commit_transaction); | 526 | trace_jbd2_commit_logging(journal, commit_transaction); |
527 | stats.run.rs_logging = jiffies; | 527 | stats.run.rs_logging = jiffies; |
528 | stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing, | 528 | stats.run.rs_flushing = jbd2_time_diff(stats.run.rs_flushing, |
529 | stats.run.rs_logging); | 529 | stats.run.rs_logging); |
530 | stats.run.rs_blocks = commit_transaction->t_outstanding_credits; | 530 | stats.run.rs_blocks = |
531 | atomic_read(&commit_transaction->t_outstanding_credits); | ||
531 | stats.run.rs_blocks_logged = 0; | 532 | stats.run.rs_blocks_logged = 0; |
532 | 533 | ||
533 | J_ASSERT(commit_transaction->t_nr_buffers <= | 534 | J_ASSERT(commit_transaction->t_nr_buffers <= |
534 | commit_transaction->t_outstanding_credits); | 535 | atomic_read(&commit_transaction->t_outstanding_credits)); |
535 | 536 | ||
536 | err = 0; | 537 | err = 0; |
537 | descriptor = NULL; | 538 | descriptor = NULL; |
@@ -616,7 +617,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
616 | * the free space in the log, but this counter is changed | 617 | * the free space in the log, but this counter is changed |
617 | * by jbd2_journal_next_log_block() also. | 618 | * by jbd2_journal_next_log_block() also. |
618 | */ | 619 | */ |
619 | commit_transaction->t_outstanding_credits--; | 620 | atomic_dec(&commit_transaction->t_outstanding_credits); |
620 | 621 | ||
621 | /* Bump b_count to prevent truncate from stumbling over | 622 | /* Bump b_count to prevent truncate from stumbling over |
622 | the shadowed buffer! @@@ This can go if we ever get | 623 | the shadowed buffer! @@@ This can go if we ever get |
@@ -977,7 +978,7 @@ restart_loop: | |||
977 | * __jbd2_journal_drop_transaction(). Otherwise we could race with | 978 | * __jbd2_journal_drop_transaction(). Otherwise we could race with |
978 | * other checkpointing code processing the transaction... | 979 | * other checkpointing code processing the transaction... |
979 | */ | 980 | */ |
980 | spin_lock(&journal->j_state_lock); | 981 | write_lock(&journal->j_state_lock); |
981 | spin_lock(&journal->j_list_lock); | 982 | spin_lock(&journal->j_list_lock); |
982 | /* | 983 | /* |
983 | * Now recheck if some buffers did not get attached to the transaction | 984 | * Now recheck if some buffers did not get attached to the transaction |
@@ -985,7 +986,7 @@ restart_loop: | |||
985 | */ | 986 | */ |
986 | if (commit_transaction->t_forget) { | 987 | if (commit_transaction->t_forget) { |
987 | spin_unlock(&journal->j_list_lock); | 988 | spin_unlock(&journal->j_list_lock); |
988 | spin_unlock(&journal->j_state_lock); | 989 | write_unlock(&journal->j_state_lock); |
989 | goto restart_loop; | 990 | goto restart_loop; |
990 | } | 991 | } |
991 | 992 | ||
@@ -1003,7 +1004,8 @@ restart_loop: | |||
1003 | * File the transaction statistics | 1004 | * File the transaction statistics |
1004 | */ | 1005 | */ |
1005 | stats.ts_tid = commit_transaction->t_tid; | 1006 | stats.ts_tid = commit_transaction->t_tid; |
1006 | stats.run.rs_handle_count = commit_transaction->t_handle_count; | 1007 | stats.run.rs_handle_count = |
1008 | atomic_read(&commit_transaction->t_handle_count); | ||
1007 | trace_jbd2_run_stats(journal->j_fs_dev->bd_dev, | 1009 | trace_jbd2_run_stats(journal->j_fs_dev->bd_dev, |
1008 | commit_transaction->t_tid, &stats.run); | 1010 | commit_transaction->t_tid, &stats.run); |
1009 | 1011 | ||
@@ -1037,7 +1039,7 @@ restart_loop: | |||
1037 | journal->j_average_commit_time*3) / 4; | 1039 | journal->j_average_commit_time*3) / 4; |
1038 | else | 1040 | else |
1039 | journal->j_average_commit_time = commit_time; | 1041 | journal->j_average_commit_time = commit_time; |
1040 | spin_unlock(&journal->j_state_lock); | 1042 | write_unlock(&journal->j_state_lock); |
1041 | 1043 | ||
1042 | if (commit_transaction->t_checkpoint_list == NULL && | 1044 | if (commit_transaction->t_checkpoint_list == NULL && |
1043 | commit_transaction->t_checkpoint_io_list == NULL) { | 1045 | commit_transaction->t_checkpoint_io_list == NULL) { |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index bc2ff5932769..ad5866aaf0f9 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/hash.h> | 41 | #include <linux/hash.h> |
42 | #include <linux/log2.h> | 42 | #include <linux/log2.h> |
43 | #include <linux/vmalloc.h> | 43 | #include <linux/vmalloc.h> |
44 | #include <linux/backing-dev.h> | ||
44 | 45 | ||
45 | #define CREATE_TRACE_POINTS | 46 | #define CREATE_TRACE_POINTS |
46 | #include <trace/events/jbd2.h> | 47 | #include <trace/events/jbd2.h> |
@@ -48,8 +49,6 @@ | |||
48 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
49 | #include <asm/page.h> | 50 | #include <asm/page.h> |
50 | 51 | ||
51 | EXPORT_SYMBOL(jbd2_journal_start); | ||
52 | EXPORT_SYMBOL(jbd2_journal_restart); | ||
53 | EXPORT_SYMBOL(jbd2_journal_extend); | 52 | EXPORT_SYMBOL(jbd2_journal_extend); |
54 | EXPORT_SYMBOL(jbd2_journal_stop); | 53 | EXPORT_SYMBOL(jbd2_journal_stop); |
55 | EXPORT_SYMBOL(jbd2_journal_lock_updates); | 54 | EXPORT_SYMBOL(jbd2_journal_lock_updates); |
@@ -143,7 +142,7 @@ static int kjournald2(void *arg) | |||
143 | /* | 142 | /* |
144 | * And now, wait forever for commit wakeup events. | 143 | * And now, wait forever for commit wakeup events. |
145 | */ | 144 | */ |
146 | spin_lock(&journal->j_state_lock); | 145 | write_lock(&journal->j_state_lock); |
147 | 146 | ||
148 | loop: | 147 | loop: |
149 | if (journal->j_flags & JBD2_UNMOUNT) | 148 | if (journal->j_flags & JBD2_UNMOUNT) |
@@ -154,10 +153,10 @@ loop: | |||
154 | 153 | ||
155 | if (journal->j_commit_sequence != journal->j_commit_request) { | 154 | if (journal->j_commit_sequence != journal->j_commit_request) { |
156 | jbd_debug(1, "OK, requests differ\n"); | 155 | jbd_debug(1, "OK, requests differ\n"); |
157 | spin_unlock(&journal->j_state_lock); | 156 | write_unlock(&journal->j_state_lock); |
158 | del_timer_sync(&journal->j_commit_timer); | 157 | del_timer_sync(&journal->j_commit_timer); |
159 | jbd2_journal_commit_transaction(journal); | 158 | jbd2_journal_commit_transaction(journal); |
160 | spin_lock(&journal->j_state_lock); | 159 | write_lock(&journal->j_state_lock); |
161 | goto loop; | 160 | goto loop; |
162 | } | 161 | } |
163 | 162 | ||
@@ -169,9 +168,9 @@ loop: | |||
169 | * be already stopped. | 168 | * be already stopped. |
170 | */ | 169 | */ |
171 | jbd_debug(1, "Now suspending kjournald2\n"); | 170 | jbd_debug(1, "Now suspending kjournald2\n"); |
172 | spin_unlock(&journal->j_state_lock); | 171 | write_unlock(&journal->j_state_lock); |
173 | refrigerator(); | 172 | refrigerator(); |
174 | spin_lock(&journal->j_state_lock); | 173 | write_lock(&journal->j_state_lock); |
175 | } else { | 174 | } else { |
176 | /* | 175 | /* |
177 | * We assume on resume that commits are already there, | 176 | * We assume on resume that commits are already there, |
@@ -191,9 +190,9 @@ loop: | |||
191 | if (journal->j_flags & JBD2_UNMOUNT) | 190 | if (journal->j_flags & JBD2_UNMOUNT) |
192 | should_sleep = 0; | 191 | should_sleep = 0; |
193 | if (should_sleep) { | 192 | if (should_sleep) { |
194 | spin_unlock(&journal->j_state_lock); | 193 | write_unlock(&journal->j_state_lock); |
195 | schedule(); | 194 | schedule(); |
196 | spin_lock(&journal->j_state_lock); | 195 | write_lock(&journal->j_state_lock); |
197 | } | 196 | } |
198 | finish_wait(&journal->j_wait_commit, &wait); | 197 | finish_wait(&journal->j_wait_commit, &wait); |
199 | } | 198 | } |
@@ -211,7 +210,7 @@ loop: | |||
211 | goto loop; | 210 | goto loop; |
212 | 211 | ||
213 | end_loop: | 212 | end_loop: |
214 | spin_unlock(&journal->j_state_lock); | 213 | write_unlock(&journal->j_state_lock); |
215 | del_timer_sync(&journal->j_commit_timer); | 214 | del_timer_sync(&journal->j_commit_timer); |
216 | journal->j_task = NULL; | 215 | journal->j_task = NULL; |
217 | wake_up(&journal->j_wait_done_commit); | 216 | wake_up(&journal->j_wait_done_commit); |
@@ -234,16 +233,16 @@ static int jbd2_journal_start_thread(journal_t *journal) | |||
234 | 233 | ||
235 | static void journal_kill_thread(journal_t *journal) | 234 | static void journal_kill_thread(journal_t *journal) |
236 | { | 235 | { |
237 | spin_lock(&journal->j_state_lock); | 236 | write_lock(&journal->j_state_lock); |
238 | journal->j_flags |= JBD2_UNMOUNT; | 237 | journal->j_flags |= JBD2_UNMOUNT; |
239 | 238 | ||
240 | while (journal->j_task) { | 239 | while (journal->j_task) { |
241 | wake_up(&journal->j_wait_commit); | 240 | wake_up(&journal->j_wait_commit); |
242 | spin_unlock(&journal->j_state_lock); | 241 | write_unlock(&journal->j_state_lock); |
243 | wait_event(journal->j_wait_done_commit, journal->j_task == NULL); | 242 | wait_event(journal->j_wait_done_commit, journal->j_task == NULL); |
244 | spin_lock(&journal->j_state_lock); | 243 | write_lock(&journal->j_state_lock); |
245 | } | 244 | } |
246 | spin_unlock(&journal->j_state_lock); | 245 | write_unlock(&journal->j_state_lock); |
247 | } | 246 | } |
248 | 247 | ||
249 | /* | 248 | /* |
@@ -297,7 +296,6 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction, | |||
297 | struct page *new_page; | 296 | struct page *new_page; |
298 | unsigned int new_offset; | 297 | unsigned int new_offset; |
299 | struct buffer_head *bh_in = jh2bh(jh_in); | 298 | struct buffer_head *bh_in = jh2bh(jh_in); |
300 | struct jbd2_buffer_trigger_type *triggers; | ||
301 | journal_t *journal = transaction->t_journal; | 299 | journal_t *journal = transaction->t_journal; |
302 | 300 | ||
303 | /* | 301 | /* |
@@ -311,7 +309,17 @@ int jbd2_journal_write_metadata_buffer(transaction_t *transaction, | |||
311 | */ | 309 | */ |
312 | J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in)); | 310 | J_ASSERT_BH(bh_in, buffer_jbddirty(bh_in)); |
313 | 311 | ||
314 | new_bh = alloc_buffer_head(GFP_NOFS|__GFP_NOFAIL); | 312 | retry_alloc: |
313 | new_bh = alloc_buffer_head(GFP_NOFS); | ||
314 | if (!new_bh) { | ||
315 | /* | ||
316 | * Failure is not an option, but __GFP_NOFAIL is going | ||
317 | * away; so we retry ourselves here. | ||
318 | */ | ||
319 | congestion_wait(BLK_RW_ASYNC, HZ/50); | ||
320 | goto retry_alloc; | ||
321 | } | ||
322 | |||
315 | /* keep subsequent assertions sane */ | 323 | /* keep subsequent assertions sane */ |
316 | new_bh->b_state = 0; | 324 | new_bh->b_state = 0; |
317 | init_buffer(new_bh, NULL, NULL); | 325 | init_buffer(new_bh, NULL, NULL); |
@@ -328,21 +336,21 @@ repeat: | |||
328 | done_copy_out = 1; | 336 | done_copy_out = 1; |
329 | new_page = virt_to_page(jh_in->b_frozen_data); | 337 | new_page = virt_to_page(jh_in->b_frozen_data); |
330 | new_offset = offset_in_page(jh_in->b_frozen_data); | 338 | new_offset = offset_in_page(jh_in->b_frozen_data); |
331 | triggers = jh_in->b_frozen_triggers; | ||
332 | } else { | 339 | } else { |
333 | new_page = jh2bh(jh_in)->b_page; | 340 | new_page = jh2bh(jh_in)->b_page; |
334 | new_offset = offset_in_page(jh2bh(jh_in)->b_data); | 341 | new_offset = offset_in_page(jh2bh(jh_in)->b_data); |
335 | triggers = jh_in->b_triggers; | ||
336 | } | 342 | } |
337 | 343 | ||
338 | mapped_data = kmap_atomic(new_page, KM_USER0); | 344 | mapped_data = kmap_atomic(new_page, KM_USER0); |
339 | /* | 345 | /* |
340 | * Fire any commit trigger. Do this before checking for escaping, | 346 | * Fire data frozen trigger if data already wasn't frozen. Do this |
341 | * as the trigger may modify the magic offset. If a copy-out | 347 | * before checking for escaping, as the trigger may modify the magic |
342 | * happens afterwards, it will have the correct data in the buffer. | 348 | * offset. If a copy-out happens afterwards, it will have the correct |
349 | * data in the buffer. | ||
343 | */ | 350 | */ |
344 | jbd2_buffer_commit_trigger(jh_in, mapped_data + new_offset, | 351 | if (!done_copy_out) |
345 | triggers); | 352 | jbd2_buffer_frozen_trigger(jh_in, mapped_data + new_offset, |
353 | jh_in->b_triggers); | ||
346 | 354 | ||
347 | /* | 355 | /* |
348 | * Check for escaping | 356 | * Check for escaping |
@@ -443,7 +451,7 @@ int __jbd2_log_space_left(journal_t *journal) | |||
443 | { | 451 | { |
444 | int left = journal->j_free; | 452 | int left = journal->j_free; |
445 | 453 | ||
446 | assert_spin_locked(&journal->j_state_lock); | 454 | /* assert_spin_locked(&journal->j_state_lock); */ |
447 | 455 | ||
448 | /* | 456 | /* |
449 | * Be pessimistic here about the number of those free blocks which | 457 | * Be pessimistic here about the number of those free blocks which |
@@ -488,9 +496,9 @@ int jbd2_log_start_commit(journal_t *journal, tid_t tid) | |||
488 | { | 496 | { |
489 | int ret; | 497 | int ret; |
490 | 498 | ||
491 | spin_lock(&journal->j_state_lock); | 499 | write_lock(&journal->j_state_lock); |
492 | ret = __jbd2_log_start_commit(journal, tid); | 500 | ret = __jbd2_log_start_commit(journal, tid); |
493 | spin_unlock(&journal->j_state_lock); | 501 | write_unlock(&journal->j_state_lock); |
494 | return ret; | 502 | return ret; |
495 | } | 503 | } |
496 | 504 | ||
@@ -509,7 +517,7 @@ int jbd2_journal_force_commit_nested(journal_t *journal) | |||
509 | transaction_t *transaction = NULL; | 517 | transaction_t *transaction = NULL; |
510 | tid_t tid; | 518 | tid_t tid; |
511 | 519 | ||
512 | spin_lock(&journal->j_state_lock); | 520 | read_lock(&journal->j_state_lock); |
513 | if (journal->j_running_transaction && !current->journal_info) { | 521 | if (journal->j_running_transaction && !current->journal_info) { |
514 | transaction = journal->j_running_transaction; | 522 | transaction = journal->j_running_transaction; |
515 | __jbd2_log_start_commit(journal, transaction->t_tid); | 523 | __jbd2_log_start_commit(journal, transaction->t_tid); |
@@ -517,12 +525,12 @@ int jbd2_journal_force_commit_nested(journal_t *journal) | |||
517 | transaction = journal->j_committing_transaction; | 525 | transaction = journal->j_committing_transaction; |
518 | 526 | ||
519 | if (!transaction) { | 527 | if (!transaction) { |
520 | spin_unlock(&journal->j_state_lock); | 528 | read_unlock(&journal->j_state_lock); |
521 | return 0; /* Nothing to retry */ | 529 | return 0; /* Nothing to retry */ |
522 | } | 530 | } |
523 | 531 | ||
524 | tid = transaction->t_tid; | 532 | tid = transaction->t_tid; |
525 | spin_unlock(&journal->j_state_lock); | 533 | read_unlock(&journal->j_state_lock); |
526 | jbd2_log_wait_commit(journal, tid); | 534 | jbd2_log_wait_commit(journal, tid); |
527 | return 1; | 535 | return 1; |
528 | } | 536 | } |
@@ -536,7 +544,7 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid) | |||
536 | { | 544 | { |
537 | int ret = 0; | 545 | int ret = 0; |
538 | 546 | ||
539 | spin_lock(&journal->j_state_lock); | 547 | write_lock(&journal->j_state_lock); |
540 | if (journal->j_running_transaction) { | 548 | if (journal->j_running_transaction) { |
541 | tid_t tid = journal->j_running_transaction->t_tid; | 549 | tid_t tid = journal->j_running_transaction->t_tid; |
542 | 550 | ||
@@ -555,7 +563,7 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid) | |||
555 | *ptid = journal->j_committing_transaction->t_tid; | 563 | *ptid = journal->j_committing_transaction->t_tid; |
556 | ret = 1; | 564 | ret = 1; |
557 | } | 565 | } |
558 | spin_unlock(&journal->j_state_lock); | 566 | write_unlock(&journal->j_state_lock); |
559 | return ret; | 567 | return ret; |
560 | } | 568 | } |
561 | 569 | ||
@@ -567,26 +575,24 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid) | |||
567 | { | 575 | { |
568 | int err = 0; | 576 | int err = 0; |
569 | 577 | ||
578 | read_lock(&journal->j_state_lock); | ||
570 | #ifdef CONFIG_JBD2_DEBUG | 579 | #ifdef CONFIG_JBD2_DEBUG |
571 | spin_lock(&journal->j_state_lock); | ||
572 | if (!tid_geq(journal->j_commit_request, tid)) { | 580 | if (!tid_geq(journal->j_commit_request, tid)) { |
573 | printk(KERN_EMERG | 581 | printk(KERN_EMERG |
574 | "%s: error: j_commit_request=%d, tid=%d\n", | 582 | "%s: error: j_commit_request=%d, tid=%d\n", |
575 | __func__, journal->j_commit_request, tid); | 583 | __func__, journal->j_commit_request, tid); |
576 | } | 584 | } |
577 | spin_unlock(&journal->j_state_lock); | ||
578 | #endif | 585 | #endif |
579 | spin_lock(&journal->j_state_lock); | ||
580 | while (tid_gt(tid, journal->j_commit_sequence)) { | 586 | while (tid_gt(tid, journal->j_commit_sequence)) { |
581 | jbd_debug(1, "JBD: want %d, j_commit_sequence=%d\n", | 587 | jbd_debug(1, "JBD: want %d, j_commit_sequence=%d\n", |
582 | tid, journal->j_commit_sequence); | 588 | tid, journal->j_commit_sequence); |
583 | wake_up(&journal->j_wait_commit); | 589 | wake_up(&journal->j_wait_commit); |
584 | spin_unlock(&journal->j_state_lock); | 590 | read_unlock(&journal->j_state_lock); |
585 | wait_event(journal->j_wait_done_commit, | 591 | wait_event(journal->j_wait_done_commit, |
586 | !tid_gt(tid, journal->j_commit_sequence)); | 592 | !tid_gt(tid, journal->j_commit_sequence)); |
587 | spin_lock(&journal->j_state_lock); | 593 | read_lock(&journal->j_state_lock); |
588 | } | 594 | } |
589 | spin_unlock(&journal->j_state_lock); | 595 | read_unlock(&journal->j_state_lock); |
590 | 596 | ||
591 | if (unlikely(is_journal_aborted(journal))) { | 597 | if (unlikely(is_journal_aborted(journal))) { |
592 | printk(KERN_EMERG "journal commit I/O error\n"); | 598 | printk(KERN_EMERG "journal commit I/O error\n"); |
@@ -603,7 +609,7 @@ int jbd2_journal_next_log_block(journal_t *journal, unsigned long long *retp) | |||
603 | { | 609 | { |
604 | unsigned long blocknr; | 610 | unsigned long blocknr; |
605 | 611 | ||
606 | spin_lock(&journal->j_state_lock); | 612 | write_lock(&journal->j_state_lock); |
607 | J_ASSERT(journal->j_free > 1); | 613 | J_ASSERT(journal->j_free > 1); |
608 | 614 | ||
609 | blocknr = journal->j_head; | 615 | blocknr = journal->j_head; |
@@ -611,7 +617,7 @@ int jbd2_journal_next_log_block(journal_t *journal, unsigned long long *retp) | |||
611 | journal->j_free--; | 617 | journal->j_free--; |
612 | if (journal->j_head == journal->j_last) | 618 | if (journal->j_head == journal->j_last) |
613 | journal->j_head = journal->j_first; | 619 | journal->j_head = journal->j_first; |
614 | spin_unlock(&journal->j_state_lock); | 620 | write_unlock(&journal->j_state_lock); |
615 | return jbd2_journal_bmap(journal, blocknr, retp); | 621 | return jbd2_journal_bmap(journal, blocknr, retp); |
616 | } | 622 | } |
617 | 623 | ||
@@ -831,7 +837,7 @@ static journal_t * journal_init_common (void) | |||
831 | mutex_init(&journal->j_checkpoint_mutex); | 837 | mutex_init(&journal->j_checkpoint_mutex); |
832 | spin_lock_init(&journal->j_revoke_lock); | 838 | spin_lock_init(&journal->j_revoke_lock); |
833 | spin_lock_init(&journal->j_list_lock); | 839 | spin_lock_init(&journal->j_list_lock); |
834 | spin_lock_init(&journal->j_state_lock); | 840 | rwlock_init(&journal->j_state_lock); |
835 | 841 | ||
836 | journal->j_commit_interval = (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE); | 842 | journal->j_commit_interval = (HZ * JBD2_DEFAULT_MAX_COMMIT_AGE); |
837 | journal->j_min_batch_time = 0; | 843 | journal->j_min_batch_time = 0; |
@@ -1097,14 +1103,14 @@ void jbd2_journal_update_superblock(journal_t *journal, int wait) | |||
1097 | set_buffer_uptodate(bh); | 1103 | set_buffer_uptodate(bh); |
1098 | } | 1104 | } |
1099 | 1105 | ||
1100 | spin_lock(&journal->j_state_lock); | 1106 | read_lock(&journal->j_state_lock); |
1101 | jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n", | 1107 | jbd_debug(1,"JBD: updating superblock (start %ld, seq %d, errno %d)\n", |
1102 | journal->j_tail, journal->j_tail_sequence, journal->j_errno); | 1108 | journal->j_tail, journal->j_tail_sequence, journal->j_errno); |
1103 | 1109 | ||
1104 | sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); | 1110 | sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); |
1105 | sb->s_start = cpu_to_be32(journal->j_tail); | 1111 | sb->s_start = cpu_to_be32(journal->j_tail); |
1106 | sb->s_errno = cpu_to_be32(journal->j_errno); | 1112 | sb->s_errno = cpu_to_be32(journal->j_errno); |
1107 | spin_unlock(&journal->j_state_lock); | 1113 | read_unlock(&journal->j_state_lock); |
1108 | 1114 | ||
1109 | BUFFER_TRACE(bh, "marking dirty"); | 1115 | BUFFER_TRACE(bh, "marking dirty"); |
1110 | mark_buffer_dirty(bh); | 1116 | mark_buffer_dirty(bh); |
@@ -1125,12 +1131,12 @@ out: | |||
1125 | * any future commit will have to be careful to update the | 1131 | * any future commit will have to be careful to update the |
1126 | * superblock again to re-record the true start of the log. */ | 1132 | * superblock again to re-record the true start of the log. */ |
1127 | 1133 | ||
1128 | spin_lock(&journal->j_state_lock); | 1134 | write_lock(&journal->j_state_lock); |
1129 | if (sb->s_start) | 1135 | if (sb->s_start) |
1130 | journal->j_flags &= ~JBD2_FLUSHED; | 1136 | journal->j_flags &= ~JBD2_FLUSHED; |
1131 | else | 1137 | else |
1132 | journal->j_flags |= JBD2_FLUSHED; | 1138 | journal->j_flags |= JBD2_FLUSHED; |
1133 | spin_unlock(&journal->j_state_lock); | 1139 | write_unlock(&journal->j_state_lock); |
1134 | } | 1140 | } |
1135 | 1141 | ||
1136 | /* | 1142 | /* |
@@ -1392,13 +1398,9 @@ int jbd2_journal_check_used_features (journal_t *journal, unsigned long compat, | |||
1392 | int jbd2_journal_check_available_features (journal_t *journal, unsigned long compat, | 1398 | int jbd2_journal_check_available_features (journal_t *journal, unsigned long compat, |
1393 | unsigned long ro, unsigned long incompat) | 1399 | unsigned long ro, unsigned long incompat) |
1394 | { | 1400 | { |
1395 | journal_superblock_t *sb; | ||
1396 | |||
1397 | if (!compat && !ro && !incompat) | 1401 | if (!compat && !ro && !incompat) |
1398 | return 1; | 1402 | return 1; |
1399 | 1403 | ||
1400 | sb = journal->j_superblock; | ||
1401 | |||
1402 | /* We can support any known requested features iff the | 1404 | /* We can support any known requested features iff the |
1403 | * superblock is in version 2. Otherwise we fail to support any | 1405 | * superblock is in version 2. Otherwise we fail to support any |
1404 | * extended sb features. */ | 1406 | * extended sb features. */ |
@@ -1546,7 +1548,7 @@ int jbd2_journal_flush(journal_t *journal) | |||
1546 | transaction_t *transaction = NULL; | 1548 | transaction_t *transaction = NULL; |
1547 | unsigned long old_tail; | 1549 | unsigned long old_tail; |
1548 | 1550 | ||
1549 | spin_lock(&journal->j_state_lock); | 1551 | write_lock(&journal->j_state_lock); |
1550 | 1552 | ||
1551 | /* Force everything buffered to the log... */ | 1553 | /* Force everything buffered to the log... */ |
1552 | if (journal->j_running_transaction) { | 1554 | if (journal->j_running_transaction) { |
@@ -1559,10 +1561,10 @@ int jbd2_journal_flush(journal_t *journal) | |||
1559 | if (transaction) { | 1561 | if (transaction) { |
1560 | tid_t tid = transaction->t_tid; | 1562 | tid_t tid = transaction->t_tid; |
1561 | 1563 | ||
1562 | spin_unlock(&journal->j_state_lock); | 1564 | write_unlock(&journal->j_state_lock); |
1563 | jbd2_log_wait_commit(journal, tid); | 1565 | jbd2_log_wait_commit(journal, tid); |
1564 | } else { | 1566 | } else { |
1565 | spin_unlock(&journal->j_state_lock); | 1567 | write_unlock(&journal->j_state_lock); |
1566 | } | 1568 | } |
1567 | 1569 | ||
1568 | /* ...and flush everything in the log out to disk. */ | 1570 | /* ...and flush everything in the log out to disk. */ |
@@ -1586,12 +1588,12 @@ int jbd2_journal_flush(journal_t *journal) | |||
1586 | * the magic code for a fully-recovered superblock. Any future | 1588 | * the magic code for a fully-recovered superblock. Any future |
1587 | * commits of data to the journal will restore the current | 1589 | * commits of data to the journal will restore the current |
1588 | * s_start value. */ | 1590 | * s_start value. */ |
1589 | spin_lock(&journal->j_state_lock); | 1591 | write_lock(&journal->j_state_lock); |
1590 | old_tail = journal->j_tail; | 1592 | old_tail = journal->j_tail; |
1591 | journal->j_tail = 0; | 1593 | journal->j_tail = 0; |
1592 | spin_unlock(&journal->j_state_lock); | 1594 | write_unlock(&journal->j_state_lock); |
1593 | jbd2_journal_update_superblock(journal, 1); | 1595 | jbd2_journal_update_superblock(journal, 1); |
1594 | spin_lock(&journal->j_state_lock); | 1596 | write_lock(&journal->j_state_lock); |
1595 | journal->j_tail = old_tail; | 1597 | journal->j_tail = old_tail; |
1596 | 1598 | ||
1597 | J_ASSERT(!journal->j_running_transaction); | 1599 | J_ASSERT(!journal->j_running_transaction); |
@@ -1599,7 +1601,7 @@ int jbd2_journal_flush(journal_t *journal) | |||
1599 | J_ASSERT(!journal->j_checkpoint_transactions); | 1601 | J_ASSERT(!journal->j_checkpoint_transactions); |
1600 | J_ASSERT(journal->j_head == journal->j_tail); | 1602 | J_ASSERT(journal->j_head == journal->j_tail); |
1601 | J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); | 1603 | J_ASSERT(journal->j_tail_sequence == journal->j_transaction_sequence); |
1602 | spin_unlock(&journal->j_state_lock); | 1604 | write_unlock(&journal->j_state_lock); |
1603 | return 0; | 1605 | return 0; |
1604 | } | 1606 | } |
1605 | 1607 | ||
@@ -1618,7 +1620,6 @@ int jbd2_journal_flush(journal_t *journal) | |||
1618 | 1620 | ||
1619 | int jbd2_journal_wipe(journal_t *journal, int write) | 1621 | int jbd2_journal_wipe(journal_t *journal, int write) |
1620 | { | 1622 | { |
1621 | journal_superblock_t *sb; | ||
1622 | int err = 0; | 1623 | int err = 0; |
1623 | 1624 | ||
1624 | J_ASSERT (!(journal->j_flags & JBD2_LOADED)); | 1625 | J_ASSERT (!(journal->j_flags & JBD2_LOADED)); |
@@ -1627,8 +1628,6 @@ int jbd2_journal_wipe(journal_t *journal, int write) | |||
1627 | if (err) | 1628 | if (err) |
1628 | return err; | 1629 | return err; |
1629 | 1630 | ||
1630 | sb = journal->j_superblock; | ||
1631 | |||
1632 | if (!journal->j_tail) | 1631 | if (!journal->j_tail) |
1633 | goto no_recovery; | 1632 | goto no_recovery; |
1634 | 1633 | ||
@@ -1666,12 +1665,12 @@ void __jbd2_journal_abort_hard(journal_t *journal) | |||
1666 | printk(KERN_ERR "Aborting journal on device %s.\n", | 1665 | printk(KERN_ERR "Aborting journal on device %s.\n", |
1667 | journal->j_devname); | 1666 | journal->j_devname); |
1668 | 1667 | ||
1669 | spin_lock(&journal->j_state_lock); | 1668 | write_lock(&journal->j_state_lock); |
1670 | journal->j_flags |= JBD2_ABORT; | 1669 | journal->j_flags |= JBD2_ABORT; |
1671 | transaction = journal->j_running_transaction; | 1670 | transaction = journal->j_running_transaction; |
1672 | if (transaction) | 1671 | if (transaction) |
1673 | __jbd2_log_start_commit(journal, transaction->t_tid); | 1672 | __jbd2_log_start_commit(journal, transaction->t_tid); |
1674 | spin_unlock(&journal->j_state_lock); | 1673 | write_unlock(&journal->j_state_lock); |
1675 | } | 1674 | } |
1676 | 1675 | ||
1677 | /* Soft abort: record the abort error status in the journal superblock, | 1676 | /* Soft abort: record the abort error status in the journal superblock, |
@@ -1756,12 +1755,12 @@ int jbd2_journal_errno(journal_t *journal) | |||
1756 | { | 1755 | { |
1757 | int err; | 1756 | int err; |
1758 | 1757 | ||
1759 | spin_lock(&journal->j_state_lock); | 1758 | read_lock(&journal->j_state_lock); |
1760 | if (journal->j_flags & JBD2_ABORT) | 1759 | if (journal->j_flags & JBD2_ABORT) |
1761 | err = -EROFS; | 1760 | err = -EROFS; |
1762 | else | 1761 | else |
1763 | err = journal->j_errno; | 1762 | err = journal->j_errno; |
1764 | spin_unlock(&journal->j_state_lock); | 1763 | read_unlock(&journal->j_state_lock); |
1765 | return err; | 1764 | return err; |
1766 | } | 1765 | } |
1767 | 1766 | ||
@@ -1776,12 +1775,12 @@ int jbd2_journal_clear_err(journal_t *journal) | |||
1776 | { | 1775 | { |
1777 | int err = 0; | 1776 | int err = 0; |
1778 | 1777 | ||
1779 | spin_lock(&journal->j_state_lock); | 1778 | write_lock(&journal->j_state_lock); |
1780 | if (journal->j_flags & JBD2_ABORT) | 1779 | if (journal->j_flags & JBD2_ABORT) |
1781 | err = -EROFS; | 1780 | err = -EROFS; |
1782 | else | 1781 | else |
1783 | journal->j_errno = 0; | 1782 | journal->j_errno = 0; |
1784 | spin_unlock(&journal->j_state_lock); | 1783 | write_unlock(&journal->j_state_lock); |
1785 | return err; | 1784 | return err; |
1786 | } | 1785 | } |
1787 | 1786 | ||
@@ -1794,10 +1793,10 @@ int jbd2_journal_clear_err(journal_t *journal) | |||
1794 | */ | 1793 | */ |
1795 | void jbd2_journal_ack_err(journal_t *journal) | 1794 | void jbd2_journal_ack_err(journal_t *journal) |
1796 | { | 1795 | { |
1797 | spin_lock(&journal->j_state_lock); | 1796 | write_lock(&journal->j_state_lock); |
1798 | if (journal->j_errno) | 1797 | if (journal->j_errno) |
1799 | journal->j_flags |= JBD2_ACK_ERR; | 1798 | journal->j_flags |= JBD2_ACK_ERR; |
1800 | spin_unlock(&journal->j_state_lock); | 1799 | write_unlock(&journal->j_state_lock); |
1801 | } | 1800 | } |
1802 | 1801 | ||
1803 | int jbd2_journal_blocks_per_page(struct inode *inode) | 1802 | int jbd2_journal_blocks_per_page(struct inode *inode) |
@@ -2202,8 +2201,6 @@ void jbd2_journal_init_jbd_inode(struct jbd2_inode *jinode, struct inode *inode) | |||
2202 | void jbd2_journal_release_jbd_inode(journal_t *journal, | 2201 | void jbd2_journal_release_jbd_inode(journal_t *journal, |
2203 | struct jbd2_inode *jinode) | 2202 | struct jbd2_inode *jinode) |
2204 | { | 2203 | { |
2205 | int writeout = 0; | ||
2206 | |||
2207 | if (!journal) | 2204 | if (!journal) |
2208 | return; | 2205 | return; |
2209 | restart: | 2206 | restart: |
@@ -2220,9 +2217,6 @@ restart: | |||
2220 | goto restart; | 2217 | goto restart; |
2221 | } | 2218 | } |
2222 | 2219 | ||
2223 | /* Do we need to wait for data writeback? */ | ||
2224 | if (journal->j_committing_transaction == jinode->i_transaction) | ||
2225 | writeout = 1; | ||
2226 | if (jinode->i_transaction) { | 2220 | if (jinode->i_transaction) { |
2227 | list_del(&jinode->i_list); | 2221 | list_del(&jinode->i_list); |
2228 | jinode->i_transaction = NULL; | 2222 | jinode->i_transaction = NULL; |
diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 049281b7cb89..2bc4d5f116f1 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c | |||
@@ -285,12 +285,10 @@ int jbd2_journal_recover(journal_t *journal) | |||
285 | int jbd2_journal_skip_recovery(journal_t *journal) | 285 | int jbd2_journal_skip_recovery(journal_t *journal) |
286 | { | 286 | { |
287 | int err; | 287 | int err; |
288 | journal_superblock_t * sb; | ||
289 | 288 | ||
290 | struct recovery_info info; | 289 | struct recovery_info info; |
291 | 290 | ||
292 | memset (&info, 0, sizeof(info)); | 291 | memset (&info, 0, sizeof(info)); |
293 | sb = journal->j_superblock; | ||
294 | 292 | ||
295 | err = do_one_pass(journal, &info, PASS_SCAN); | 293 | err = do_one_pass(journal, &info, PASS_SCAN); |
296 | 294 | ||
@@ -299,7 +297,8 @@ int jbd2_journal_skip_recovery(journal_t *journal) | |||
299 | ++journal->j_transaction_sequence; | 297 | ++journal->j_transaction_sequence; |
300 | } else { | 298 | } else { |
301 | #ifdef CONFIG_JBD2_DEBUG | 299 | #ifdef CONFIG_JBD2_DEBUG |
302 | int dropped = info.end_transaction - be32_to_cpu(sb->s_sequence); | 300 | int dropped = info.end_transaction - |
301 | be32_to_cpu(journal->j_superblock->s_sequence); | ||
303 | #endif | 302 | #endif |
304 | jbd_debug(1, | 303 | jbd_debug(1, |
305 | "JBD: ignoring %d transaction%s from the journal.\n", | 304 | "JBD: ignoring %d transaction%s from the journal.\n", |
@@ -365,11 +364,6 @@ static int do_one_pass(journal_t *journal, | |||
365 | int tag_bytes = journal_tag_bytes(journal); | 364 | int tag_bytes = journal_tag_bytes(journal); |
366 | __u32 crc32_sum = ~0; /* Transactional Checksums */ | 365 | __u32 crc32_sum = ~0; /* Transactional Checksums */ |
367 | 366 | ||
368 | /* Precompute the maximum metadata descriptors in a descriptor block */ | ||
369 | int MAX_BLOCKS_PER_DESC; | ||
370 | MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t)) | ||
371 | / tag_bytes); | ||
372 | |||
373 | /* | 367 | /* |
374 | * First thing is to establish what we expect to find in the log | 368 | * First thing is to establish what we expect to find in the log |
375 | * (in terms of transaction IDs), and where (in terms of log | 369 | * (in terms of transaction IDs), and where (in terms of log |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index e214d68620ac..d95cc9d0401d 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
27 | #include <linux/highmem.h> | 27 | #include <linux/highmem.h> |
28 | #include <linux/hrtimer.h> | 28 | #include <linux/hrtimer.h> |
29 | #include <linux/backing-dev.h> | ||
30 | #include <linux/module.h> | ||
29 | 31 | ||
30 | static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh); | 32 | static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh); |
31 | 33 | ||
@@ -53,6 +55,9 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction) | |||
53 | transaction->t_tid = journal->j_transaction_sequence++; | 55 | transaction->t_tid = journal->j_transaction_sequence++; |
54 | transaction->t_expires = jiffies + journal->j_commit_interval; | 56 | transaction->t_expires = jiffies + journal->j_commit_interval; |
55 | spin_lock_init(&transaction->t_handle_lock); | 57 | spin_lock_init(&transaction->t_handle_lock); |
58 | atomic_set(&transaction->t_updates, 0); | ||
59 | atomic_set(&transaction->t_outstanding_credits, 0); | ||
60 | atomic_set(&transaction->t_handle_count, 0); | ||
56 | INIT_LIST_HEAD(&transaction->t_inode_list); | 61 | INIT_LIST_HEAD(&transaction->t_inode_list); |
57 | INIT_LIST_HEAD(&transaction->t_private_list); | 62 | INIT_LIST_HEAD(&transaction->t_private_list); |
58 | 63 | ||
@@ -83,65 +88,75 @@ jbd2_get_transaction(journal_t *journal, transaction_t *transaction) | |||
83 | * transaction's buffer credits. | 88 | * transaction's buffer credits. |
84 | */ | 89 | */ |
85 | 90 | ||
86 | static int start_this_handle(journal_t *journal, handle_t *handle) | 91 | static int start_this_handle(journal_t *journal, handle_t *handle, |
92 | int gfp_mask) | ||
87 | { | 93 | { |
88 | transaction_t *transaction; | 94 | transaction_t *transaction; |
89 | int needed; | 95 | int needed; |
90 | int nblocks = handle->h_buffer_credits; | 96 | int nblocks = handle->h_buffer_credits; |
91 | transaction_t *new_transaction = NULL; | 97 | transaction_t *new_transaction = NULL; |
92 | int ret = 0; | ||
93 | unsigned long ts = jiffies; | 98 | unsigned long ts = jiffies; |
94 | 99 | ||
95 | if (nblocks > journal->j_max_transaction_buffers) { | 100 | if (nblocks > journal->j_max_transaction_buffers) { |
96 | printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n", | 101 | printk(KERN_ERR "JBD: %s wants too many credits (%d > %d)\n", |
97 | current->comm, nblocks, | 102 | current->comm, nblocks, |
98 | journal->j_max_transaction_buffers); | 103 | journal->j_max_transaction_buffers); |
99 | ret = -ENOSPC; | 104 | return -ENOSPC; |
100 | goto out; | ||
101 | } | 105 | } |
102 | 106 | ||
103 | alloc_transaction: | 107 | alloc_transaction: |
104 | if (!journal->j_running_transaction) { | 108 | if (!journal->j_running_transaction) { |
105 | new_transaction = kzalloc(sizeof(*new_transaction), | 109 | new_transaction = kzalloc(sizeof(*new_transaction), gfp_mask); |
106 | GFP_NOFS|__GFP_NOFAIL); | ||
107 | if (!new_transaction) { | 110 | if (!new_transaction) { |
108 | ret = -ENOMEM; | 111 | /* |
109 | goto out; | 112 | * If __GFP_FS is not present, then we may be |
113 | * being called from inside the fs writeback | ||
114 | * layer, so we MUST NOT fail. Since | ||
115 | * __GFP_NOFAIL is going away, we will arrange | ||
116 | * to retry the allocation ourselves. | ||
117 | */ | ||
118 | if ((gfp_mask & __GFP_FS) == 0) { | ||
119 | congestion_wait(BLK_RW_ASYNC, HZ/50); | ||
120 | goto alloc_transaction; | ||
121 | } | ||
122 | return -ENOMEM; | ||
110 | } | 123 | } |
111 | } | 124 | } |
112 | 125 | ||
113 | jbd_debug(3, "New handle %p going live.\n", handle); | 126 | jbd_debug(3, "New handle %p going live.\n", handle); |
114 | 127 | ||
115 | repeat: | ||
116 | |||
117 | /* | 128 | /* |
118 | * We need to hold j_state_lock until t_updates has been incremented, | 129 | * We need to hold j_state_lock until t_updates has been incremented, |
119 | * for proper journal barrier handling | 130 | * for proper journal barrier handling |
120 | */ | 131 | */ |
121 | spin_lock(&journal->j_state_lock); | 132 | repeat: |
122 | repeat_locked: | 133 | read_lock(&journal->j_state_lock); |
123 | if (is_journal_aborted(journal) || | 134 | if (is_journal_aborted(journal) || |
124 | (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) { | 135 | (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) { |
125 | spin_unlock(&journal->j_state_lock); | 136 | read_unlock(&journal->j_state_lock); |
126 | ret = -EROFS; | 137 | kfree(new_transaction); |
127 | goto out; | 138 | return -EROFS; |
128 | } | 139 | } |
129 | 140 | ||
130 | /* Wait on the journal's transaction barrier if necessary */ | 141 | /* Wait on the journal's transaction barrier if necessary */ |
131 | if (journal->j_barrier_count) { | 142 | if (journal->j_barrier_count) { |
132 | spin_unlock(&journal->j_state_lock); | 143 | read_unlock(&journal->j_state_lock); |
133 | wait_event(journal->j_wait_transaction_locked, | 144 | wait_event(journal->j_wait_transaction_locked, |
134 | journal->j_barrier_count == 0); | 145 | journal->j_barrier_count == 0); |
135 | goto repeat; | 146 | goto repeat; |
136 | } | 147 | } |
137 | 148 | ||
138 | if (!journal->j_running_transaction) { | 149 | if (!journal->j_running_transaction) { |
139 | if (!new_transaction) { | 150 | read_unlock(&journal->j_state_lock); |
140 | spin_unlock(&journal->j_state_lock); | 151 | if (!new_transaction) |
141 | goto alloc_transaction; | 152 | goto alloc_transaction; |
153 | write_lock(&journal->j_state_lock); | ||
154 | if (!journal->j_running_transaction) { | ||
155 | jbd2_get_transaction(journal, new_transaction); | ||
156 | new_transaction = NULL; | ||
142 | } | 157 | } |
143 | jbd2_get_transaction(journal, new_transaction); | 158 | write_unlock(&journal->j_state_lock); |
144 | new_transaction = NULL; | 159 | goto repeat; |
145 | } | 160 | } |
146 | 161 | ||
147 | transaction = journal->j_running_transaction; | 162 | transaction = journal->j_running_transaction; |
@@ -155,7 +170,7 @@ repeat_locked: | |||
155 | 170 | ||
156 | prepare_to_wait(&journal->j_wait_transaction_locked, | 171 | prepare_to_wait(&journal->j_wait_transaction_locked, |
157 | &wait, TASK_UNINTERRUPTIBLE); | 172 | &wait, TASK_UNINTERRUPTIBLE); |
158 | spin_unlock(&journal->j_state_lock); | 173 | read_unlock(&journal->j_state_lock); |
159 | schedule(); | 174 | schedule(); |
160 | finish_wait(&journal->j_wait_transaction_locked, &wait); | 175 | finish_wait(&journal->j_wait_transaction_locked, &wait); |
161 | goto repeat; | 176 | goto repeat; |
@@ -166,8 +181,8 @@ repeat_locked: | |||
166 | * buffers requested by this operation, we need to stall pending a log | 181 | * buffers requested by this operation, we need to stall pending a log |
167 | * checkpoint to free some more log space. | 182 | * checkpoint to free some more log space. |
168 | */ | 183 | */ |
169 | spin_lock(&transaction->t_handle_lock); | 184 | needed = atomic_add_return(nblocks, |
170 | needed = transaction->t_outstanding_credits + nblocks; | 185 | &transaction->t_outstanding_credits); |
171 | 186 | ||
172 | if (needed > journal->j_max_transaction_buffers) { | 187 | if (needed > journal->j_max_transaction_buffers) { |
173 | /* | 188 | /* |
@@ -178,11 +193,11 @@ repeat_locked: | |||
178 | DEFINE_WAIT(wait); | 193 | DEFINE_WAIT(wait); |
179 | 194 | ||
180 | jbd_debug(2, "Handle %p starting new commit...\n", handle); | 195 | jbd_debug(2, "Handle %p starting new commit...\n", handle); |
181 | spin_unlock(&transaction->t_handle_lock); | 196 | atomic_sub(nblocks, &transaction->t_outstanding_credits); |
182 | prepare_to_wait(&journal->j_wait_transaction_locked, &wait, | 197 | prepare_to_wait(&journal->j_wait_transaction_locked, &wait, |
183 | TASK_UNINTERRUPTIBLE); | 198 | TASK_UNINTERRUPTIBLE); |
184 | __jbd2_log_start_commit(journal, transaction->t_tid); | 199 | __jbd2_log_start_commit(journal, transaction->t_tid); |
185 | spin_unlock(&journal->j_state_lock); | 200 | read_unlock(&journal->j_state_lock); |
186 | schedule(); | 201 | schedule(); |
187 | finish_wait(&journal->j_wait_transaction_locked, &wait); | 202 | finish_wait(&journal->j_wait_transaction_locked, &wait); |
188 | goto repeat; | 203 | goto repeat; |
@@ -215,35 +230,48 @@ repeat_locked: | |||
215 | */ | 230 | */ |
216 | if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) { | 231 | if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) { |
217 | jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle); | 232 | jbd_debug(2, "Handle %p waiting for checkpoint...\n", handle); |
218 | spin_unlock(&transaction->t_handle_lock); | 233 | atomic_sub(nblocks, &transaction->t_outstanding_credits); |
219 | __jbd2_log_wait_for_space(journal); | 234 | read_unlock(&journal->j_state_lock); |
220 | goto repeat_locked; | 235 | write_lock(&journal->j_state_lock); |
236 | if (__jbd2_log_space_left(journal) < jbd_space_needed(journal)) | ||
237 | __jbd2_log_wait_for_space(journal); | ||
238 | write_unlock(&journal->j_state_lock); | ||
239 | goto repeat; | ||
221 | } | 240 | } |
222 | 241 | ||
223 | /* OK, account for the buffers that this operation expects to | 242 | /* OK, account for the buffers that this operation expects to |
224 | * use and add the handle to the running transaction. */ | 243 | * use and add the handle to the running transaction. |
225 | 244 | * | |
226 | if (time_after(transaction->t_start, ts)) { | 245 | * In order for t_max_wait to be reliable, it must be |
246 | * protected by a lock. But doing so will mean that | ||
247 | * start_this_handle() can not be run in parallel on SMP | ||
248 | * systems, which limits our scalability. So we only enable | ||
249 | * it when debugging is enabled. We may want to use a | ||
250 | * separate flag, eventually, so we can enable this | ||
251 | * independently of debugging. | ||
252 | */ | ||
253 | #ifdef CONFIG_JBD2_DEBUG | ||
254 | if (jbd2_journal_enable_debug && | ||
255 | time_after(transaction->t_start, ts)) { | ||
227 | ts = jbd2_time_diff(ts, transaction->t_start); | 256 | ts = jbd2_time_diff(ts, transaction->t_start); |
257 | spin_lock(&transaction->t_handle_lock); | ||
228 | if (ts > transaction->t_max_wait) | 258 | if (ts > transaction->t_max_wait) |
229 | transaction->t_max_wait = ts; | 259 | transaction->t_max_wait = ts; |
260 | spin_unlock(&transaction->t_handle_lock); | ||
230 | } | 261 | } |
231 | 262 | #endif | |
232 | handle->h_transaction = transaction; | 263 | handle->h_transaction = transaction; |
233 | transaction->t_outstanding_credits += nblocks; | 264 | atomic_inc(&transaction->t_updates); |
234 | transaction->t_updates++; | 265 | atomic_inc(&transaction->t_handle_count); |
235 | transaction->t_handle_count++; | ||
236 | jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n", | 266 | jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n", |
237 | handle, nblocks, transaction->t_outstanding_credits, | 267 | handle, nblocks, |
268 | atomic_read(&transaction->t_outstanding_credits), | ||
238 | __jbd2_log_space_left(journal)); | 269 | __jbd2_log_space_left(journal)); |
239 | spin_unlock(&transaction->t_handle_lock); | 270 | read_unlock(&journal->j_state_lock); |
240 | spin_unlock(&journal->j_state_lock); | ||
241 | 271 | ||
242 | lock_map_acquire(&handle->h_lockdep_map); | 272 | lock_map_acquire(&handle->h_lockdep_map); |
243 | out: | 273 | kfree(new_transaction); |
244 | if (unlikely(new_transaction)) /* It's usually NULL */ | 274 | return 0; |
245 | kfree(new_transaction); | ||
246 | return ret; | ||
247 | } | 275 | } |
248 | 276 | ||
249 | static struct lock_class_key jbd2_handle_key; | 277 | static struct lock_class_key jbd2_handle_key; |
@@ -278,7 +306,7 @@ static handle_t *new_handle(int nblocks) | |||
278 | * | 306 | * |
279 | * Return a pointer to a newly allocated handle, or NULL on failure | 307 | * Return a pointer to a newly allocated handle, or NULL on failure |
280 | */ | 308 | */ |
281 | handle_t *jbd2_journal_start(journal_t *journal, int nblocks) | 309 | handle_t *jbd2__journal_start(journal_t *journal, int nblocks, int gfp_mask) |
282 | { | 310 | { |
283 | handle_t *handle = journal_current_handle(); | 311 | handle_t *handle = journal_current_handle(); |
284 | int err; | 312 | int err; |
@@ -298,7 +326,7 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks) | |||
298 | 326 | ||
299 | current->journal_info = handle; | 327 | current->journal_info = handle; |
300 | 328 | ||
301 | err = start_this_handle(journal, handle); | 329 | err = start_this_handle(journal, handle, gfp_mask); |
302 | if (err < 0) { | 330 | if (err < 0) { |
303 | jbd2_free_handle(handle); | 331 | jbd2_free_handle(handle); |
304 | current->journal_info = NULL; | 332 | current->journal_info = NULL; |
@@ -308,6 +336,15 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks) | |||
308 | out: | 336 | out: |
309 | return handle; | 337 | return handle; |
310 | } | 338 | } |
339 | EXPORT_SYMBOL(jbd2__journal_start); | ||
340 | |||
341 | |||
342 | handle_t *jbd2_journal_start(journal_t *journal, int nblocks) | ||
343 | { | ||
344 | return jbd2__journal_start(journal, nblocks, GFP_NOFS); | ||
345 | } | ||
346 | EXPORT_SYMBOL(jbd2_journal_start); | ||
347 | |||
311 | 348 | ||
312 | /** | 349 | /** |
313 | * int jbd2_journal_extend() - extend buffer credits. | 350 | * int jbd2_journal_extend() - extend buffer credits. |
@@ -342,7 +379,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks) | |||
342 | 379 | ||
343 | result = 1; | 380 | result = 1; |
344 | 381 | ||
345 | spin_lock(&journal->j_state_lock); | 382 | read_lock(&journal->j_state_lock); |
346 | 383 | ||
347 | /* Don't extend a locked-down transaction! */ | 384 | /* Don't extend a locked-down transaction! */ |
348 | if (handle->h_transaction->t_state != T_RUNNING) { | 385 | if (handle->h_transaction->t_state != T_RUNNING) { |
@@ -352,7 +389,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks) | |||
352 | } | 389 | } |
353 | 390 | ||
354 | spin_lock(&transaction->t_handle_lock); | 391 | spin_lock(&transaction->t_handle_lock); |
355 | wanted = transaction->t_outstanding_credits + nblocks; | 392 | wanted = atomic_read(&transaction->t_outstanding_credits) + nblocks; |
356 | 393 | ||
357 | if (wanted > journal->j_max_transaction_buffers) { | 394 | if (wanted > journal->j_max_transaction_buffers) { |
358 | jbd_debug(3, "denied handle %p %d blocks: " | 395 | jbd_debug(3, "denied handle %p %d blocks: " |
@@ -367,14 +404,14 @@ int jbd2_journal_extend(handle_t *handle, int nblocks) | |||
367 | } | 404 | } |
368 | 405 | ||
369 | handle->h_buffer_credits += nblocks; | 406 | handle->h_buffer_credits += nblocks; |
370 | transaction->t_outstanding_credits += nblocks; | 407 | atomic_add(nblocks, &transaction->t_outstanding_credits); |
371 | result = 0; | 408 | result = 0; |
372 | 409 | ||
373 | jbd_debug(3, "extended handle %p by %d\n", handle, nblocks); | 410 | jbd_debug(3, "extended handle %p by %d\n", handle, nblocks); |
374 | unlock: | 411 | unlock: |
375 | spin_unlock(&transaction->t_handle_lock); | 412 | spin_unlock(&transaction->t_handle_lock); |
376 | error_out: | 413 | error_out: |
377 | spin_unlock(&journal->j_state_lock); | 414 | read_unlock(&journal->j_state_lock); |
378 | out: | 415 | out: |
379 | return result; | 416 | return result; |
380 | } | 417 | } |
@@ -394,8 +431,7 @@ out: | |||
394 | * transaction capabable of guaranteeing the requested number of | 431 | * transaction capabable of guaranteeing the requested number of |
395 | * credits. | 432 | * credits. |
396 | */ | 433 | */ |
397 | 434 | int jbd2__journal_restart(handle_t *handle, int nblocks, int gfp_mask) | |
398 | int jbd2_journal_restart(handle_t *handle, int nblocks) | ||
399 | { | 435 | { |
400 | transaction_t *transaction = handle->h_transaction; | 436 | transaction_t *transaction = handle->h_transaction; |
401 | journal_t *journal = transaction->t_journal; | 437 | journal_t *journal = transaction->t_journal; |
@@ -410,29 +446,35 @@ int jbd2_journal_restart(handle_t *handle, int nblocks) | |||
410 | * First unlink the handle from its current transaction, and start the | 446 | * First unlink the handle from its current transaction, and start the |
411 | * commit on that. | 447 | * commit on that. |
412 | */ | 448 | */ |
413 | J_ASSERT(transaction->t_updates > 0); | 449 | J_ASSERT(atomic_read(&transaction->t_updates) > 0); |
414 | J_ASSERT(journal_current_handle() == handle); | 450 | J_ASSERT(journal_current_handle() == handle); |
415 | 451 | ||
416 | spin_lock(&journal->j_state_lock); | 452 | read_lock(&journal->j_state_lock); |
417 | spin_lock(&transaction->t_handle_lock); | 453 | spin_lock(&transaction->t_handle_lock); |
418 | transaction->t_outstanding_credits -= handle->h_buffer_credits; | 454 | atomic_sub(handle->h_buffer_credits, |
419 | transaction->t_updates--; | 455 | &transaction->t_outstanding_credits); |
420 | 456 | if (atomic_dec_and_test(&transaction->t_updates)) | |
421 | if (!transaction->t_updates) | ||
422 | wake_up(&journal->j_wait_updates); | 457 | wake_up(&journal->j_wait_updates); |
423 | spin_unlock(&transaction->t_handle_lock); | 458 | spin_unlock(&transaction->t_handle_lock); |
424 | 459 | ||
425 | jbd_debug(2, "restarting handle %p\n", handle); | 460 | jbd_debug(2, "restarting handle %p\n", handle); |
426 | __jbd2_log_start_commit(journal, transaction->t_tid); | 461 | __jbd2_log_start_commit(journal, transaction->t_tid); |
427 | spin_unlock(&journal->j_state_lock); | 462 | read_unlock(&journal->j_state_lock); |
428 | 463 | ||
429 | lock_map_release(&handle->h_lockdep_map); | 464 | lock_map_release(&handle->h_lockdep_map); |
430 | handle->h_buffer_credits = nblocks; | 465 | handle->h_buffer_credits = nblocks; |
431 | ret = start_this_handle(journal, handle); | 466 | ret = start_this_handle(journal, handle, gfp_mask); |
432 | return ret; | 467 | return ret; |
433 | } | 468 | } |
469 | EXPORT_SYMBOL(jbd2__journal_restart); | ||
434 | 470 | ||
435 | 471 | ||
472 | int jbd2_journal_restart(handle_t *handle, int nblocks) | ||
473 | { | ||
474 | return jbd2__journal_restart(handle, nblocks, GFP_NOFS); | ||
475 | } | ||
476 | EXPORT_SYMBOL(jbd2_journal_restart); | ||
477 | |||
436 | /** | 478 | /** |
437 | * void jbd2_journal_lock_updates () - establish a transaction barrier. | 479 | * void jbd2_journal_lock_updates () - establish a transaction barrier. |
438 | * @journal: Journal to establish a barrier on. | 480 | * @journal: Journal to establish a barrier on. |
@@ -447,7 +489,7 @@ void jbd2_journal_lock_updates(journal_t *journal) | |||
447 | { | 489 | { |
448 | DEFINE_WAIT(wait); | 490 | DEFINE_WAIT(wait); |
449 | 491 | ||
450 | spin_lock(&journal->j_state_lock); | 492 | write_lock(&journal->j_state_lock); |
451 | ++journal->j_barrier_count; | 493 | ++journal->j_barrier_count; |
452 | 494 | ||
453 | /* Wait until there are no running updates */ | 495 | /* Wait until there are no running updates */ |
@@ -458,19 +500,19 @@ void jbd2_journal_lock_updates(journal_t *journal) | |||
458 | break; | 500 | break; |
459 | 501 | ||
460 | spin_lock(&transaction->t_handle_lock); | 502 | spin_lock(&transaction->t_handle_lock); |
461 | if (!transaction->t_updates) { | 503 | if (!atomic_read(&transaction->t_updates)) { |
462 | spin_unlock(&transaction->t_handle_lock); | 504 | spin_unlock(&transaction->t_handle_lock); |
463 | break; | 505 | break; |
464 | } | 506 | } |
465 | prepare_to_wait(&journal->j_wait_updates, &wait, | 507 | prepare_to_wait(&journal->j_wait_updates, &wait, |
466 | TASK_UNINTERRUPTIBLE); | 508 | TASK_UNINTERRUPTIBLE); |
467 | spin_unlock(&transaction->t_handle_lock); | 509 | spin_unlock(&transaction->t_handle_lock); |
468 | spin_unlock(&journal->j_state_lock); | 510 | write_unlock(&journal->j_state_lock); |
469 | schedule(); | 511 | schedule(); |
470 | finish_wait(&journal->j_wait_updates, &wait); | 512 | finish_wait(&journal->j_wait_updates, &wait); |
471 | spin_lock(&journal->j_state_lock); | 513 | write_lock(&journal->j_state_lock); |
472 | } | 514 | } |
473 | spin_unlock(&journal->j_state_lock); | 515 | write_unlock(&journal->j_state_lock); |
474 | 516 | ||
475 | /* | 517 | /* |
476 | * We have now established a barrier against other normal updates, but | 518 | * We have now established a barrier against other normal updates, but |
@@ -494,9 +536,9 @@ void jbd2_journal_unlock_updates (journal_t *journal) | |||
494 | J_ASSERT(journal->j_barrier_count != 0); | 536 | J_ASSERT(journal->j_barrier_count != 0); |
495 | 537 | ||
496 | mutex_unlock(&journal->j_barrier); | 538 | mutex_unlock(&journal->j_barrier); |
497 | spin_lock(&journal->j_state_lock); | 539 | write_lock(&journal->j_state_lock); |
498 | --journal->j_barrier_count; | 540 | --journal->j_barrier_count; |
499 | spin_unlock(&journal->j_state_lock); | 541 | write_unlock(&journal->j_state_lock); |
500 | wake_up(&journal->j_wait_transaction_locked); | 542 | wake_up(&journal->j_wait_transaction_locked); |
501 | } | 543 | } |
502 | 544 | ||
@@ -725,6 +767,9 @@ done: | |||
725 | page = jh2bh(jh)->b_page; | 767 | page = jh2bh(jh)->b_page; |
726 | offset = ((unsigned long) jh2bh(jh)->b_data) & ~PAGE_MASK; | 768 | offset = ((unsigned long) jh2bh(jh)->b_data) & ~PAGE_MASK; |
727 | source = kmap_atomic(page, KM_USER0); | 769 | source = kmap_atomic(page, KM_USER0); |
770 | /* Fire data frozen trigger just before we copy the data */ | ||
771 | jbd2_buffer_frozen_trigger(jh, source + offset, | ||
772 | jh->b_triggers); | ||
728 | memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size); | 773 | memcpy(jh->b_frozen_data, source+offset, jh2bh(jh)->b_size); |
729 | kunmap_atomic(source, KM_USER0); | 774 | kunmap_atomic(source, KM_USER0); |
730 | 775 | ||
@@ -963,15 +1008,15 @@ void jbd2_journal_set_triggers(struct buffer_head *bh, | |||
963 | jh->b_triggers = type; | 1008 | jh->b_triggers = type; |
964 | } | 1009 | } |
965 | 1010 | ||
966 | void jbd2_buffer_commit_trigger(struct journal_head *jh, void *mapped_data, | 1011 | void jbd2_buffer_frozen_trigger(struct journal_head *jh, void *mapped_data, |
967 | struct jbd2_buffer_trigger_type *triggers) | 1012 | struct jbd2_buffer_trigger_type *triggers) |
968 | { | 1013 | { |
969 | struct buffer_head *bh = jh2bh(jh); | 1014 | struct buffer_head *bh = jh2bh(jh); |
970 | 1015 | ||
971 | if (!triggers || !triggers->t_commit) | 1016 | if (!triggers || !triggers->t_frozen) |
972 | return; | 1017 | return; |
973 | 1018 | ||
974 | triggers->t_commit(triggers, bh, mapped_data, bh->b_size); | 1019 | triggers->t_frozen(triggers, bh, mapped_data, bh->b_size); |
975 | } | 1020 | } |
976 | 1021 | ||
977 | void jbd2_buffer_abort_trigger(struct journal_head *jh, | 1022 | void jbd2_buffer_abort_trigger(struct journal_head *jh, |
@@ -1235,7 +1280,8 @@ int jbd2_journal_stop(handle_t *handle) | |||
1235 | { | 1280 | { |
1236 | transaction_t *transaction = handle->h_transaction; | 1281 | transaction_t *transaction = handle->h_transaction; |
1237 | journal_t *journal = transaction->t_journal; | 1282 | journal_t *journal = transaction->t_journal; |
1238 | int err; | 1283 | int err, wait_for_commit = 0; |
1284 | tid_t tid; | ||
1239 | pid_t pid; | 1285 | pid_t pid; |
1240 | 1286 | ||
1241 | J_ASSERT(journal_current_handle() == handle); | 1287 | J_ASSERT(journal_current_handle() == handle); |
@@ -1243,7 +1289,7 @@ int jbd2_journal_stop(handle_t *handle) | |||
1243 | if (is_handle_aborted(handle)) | 1289 | if (is_handle_aborted(handle)) |
1244 | err = -EIO; | 1290 | err = -EIO; |
1245 | else { | 1291 | else { |
1246 | J_ASSERT(transaction->t_updates > 0); | 1292 | J_ASSERT(atomic_read(&transaction->t_updates) > 0); |
1247 | err = 0; | 1293 | err = 0; |
1248 | } | 1294 | } |
1249 | 1295 | ||
@@ -1288,9 +1334,9 @@ int jbd2_journal_stop(handle_t *handle) | |||
1288 | 1334 | ||
1289 | journal->j_last_sync_writer = pid; | 1335 | journal->j_last_sync_writer = pid; |
1290 | 1336 | ||
1291 | spin_lock(&journal->j_state_lock); | 1337 | read_lock(&journal->j_state_lock); |
1292 | commit_time = journal->j_average_commit_time; | 1338 | commit_time = journal->j_average_commit_time; |
1293 | spin_unlock(&journal->j_state_lock); | 1339 | read_unlock(&journal->j_state_lock); |
1294 | 1340 | ||
1295 | trans_time = ktime_to_ns(ktime_sub(ktime_get(), | 1341 | trans_time = ktime_to_ns(ktime_sub(ktime_get(), |
1296 | transaction->t_start_time)); | 1342 | transaction->t_start_time)); |
@@ -1311,14 +1357,8 @@ int jbd2_journal_stop(handle_t *handle) | |||
1311 | if (handle->h_sync) | 1357 | if (handle->h_sync) |
1312 | transaction->t_synchronous_commit = 1; | 1358 | transaction->t_synchronous_commit = 1; |
1313 | current->journal_info = NULL; | 1359 | current->journal_info = NULL; |
1314 | spin_lock(&transaction->t_handle_lock); | 1360 | atomic_sub(handle->h_buffer_credits, |
1315 | transaction->t_outstanding_credits -= handle->h_buffer_credits; | 1361 | &transaction->t_outstanding_credits); |
1316 | transaction->t_updates--; | ||
1317 | if (!transaction->t_updates) { | ||
1318 | wake_up(&journal->j_wait_updates); | ||
1319 | if (journal->j_barrier_count) | ||
1320 | wake_up(&journal->j_wait_transaction_locked); | ||
1321 | } | ||
1322 | 1362 | ||
1323 | /* | 1363 | /* |
1324 | * If the handle is marked SYNC, we need to set another commit | 1364 | * If the handle is marked SYNC, we need to set another commit |
@@ -1327,15 +1367,13 @@ int jbd2_journal_stop(handle_t *handle) | |||
1327 | * transaction is too old now. | 1367 | * transaction is too old now. |
1328 | */ | 1368 | */ |
1329 | if (handle->h_sync || | 1369 | if (handle->h_sync || |
1330 | transaction->t_outstanding_credits > | 1370 | (atomic_read(&transaction->t_outstanding_credits) > |
1331 | journal->j_max_transaction_buffers || | 1371 | journal->j_max_transaction_buffers) || |
1332 | time_after_eq(jiffies, transaction->t_expires)) { | 1372 | time_after_eq(jiffies, transaction->t_expires)) { |
1333 | /* Do this even for aborted journals: an abort still | 1373 | /* Do this even for aborted journals: an abort still |
1334 | * completes the commit thread, it just doesn't write | 1374 | * completes the commit thread, it just doesn't write |
1335 | * anything to disk. */ | 1375 | * anything to disk. */ |
1336 | tid_t tid = transaction->t_tid; | ||
1337 | 1376 | ||
1338 | spin_unlock(&transaction->t_handle_lock); | ||
1339 | jbd_debug(2, "transaction too old, requesting commit for " | 1377 | jbd_debug(2, "transaction too old, requesting commit for " |
1340 | "handle %p\n", handle); | 1378 | "handle %p\n", handle); |
1341 | /* This is non-blocking */ | 1379 | /* This is non-blocking */ |
@@ -1346,11 +1384,25 @@ int jbd2_journal_stop(handle_t *handle) | |||
1346 | * to wait for the commit to complete. | 1384 | * to wait for the commit to complete. |
1347 | */ | 1385 | */ |
1348 | if (handle->h_sync && !(current->flags & PF_MEMALLOC)) | 1386 | if (handle->h_sync && !(current->flags & PF_MEMALLOC)) |
1349 | err = jbd2_log_wait_commit(journal, tid); | 1387 | wait_for_commit = 1; |
1350 | } else { | ||
1351 | spin_unlock(&transaction->t_handle_lock); | ||
1352 | } | 1388 | } |
1353 | 1389 | ||
1390 | /* | ||
1391 | * Once we drop t_updates, if it goes to zero the transaction | ||
1392 | * could start commiting on us and eventually disappear. So | ||
1393 | * once we do this, we must not dereference transaction | ||
1394 | * pointer again. | ||
1395 | */ | ||
1396 | tid = transaction->t_tid; | ||
1397 | if (atomic_dec_and_test(&transaction->t_updates)) { | ||
1398 | wake_up(&journal->j_wait_updates); | ||
1399 | if (journal->j_barrier_count) | ||
1400 | wake_up(&journal->j_wait_transaction_locked); | ||
1401 | } | ||
1402 | |||
1403 | if (wait_for_commit) | ||
1404 | err = jbd2_log_wait_commit(journal, tid); | ||
1405 | |||
1354 | lock_map_release(&handle->h_lockdep_map); | 1406 | lock_map_release(&handle->h_lockdep_map); |
1355 | 1407 | ||
1356 | jbd2_free_handle(handle); | 1408 | jbd2_free_handle(handle); |
@@ -1716,7 +1768,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1716 | goto zap_buffer_unlocked; | 1768 | goto zap_buffer_unlocked; |
1717 | 1769 | ||
1718 | /* OK, we have data buffer in journaled mode */ | 1770 | /* OK, we have data buffer in journaled mode */ |
1719 | spin_lock(&journal->j_state_lock); | 1771 | write_lock(&journal->j_state_lock); |
1720 | jbd_lock_bh_state(bh); | 1772 | jbd_lock_bh_state(bh); |
1721 | spin_lock(&journal->j_list_lock); | 1773 | spin_lock(&journal->j_list_lock); |
1722 | 1774 | ||
@@ -1769,7 +1821,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1769 | jbd2_journal_put_journal_head(jh); | 1821 | jbd2_journal_put_journal_head(jh); |
1770 | spin_unlock(&journal->j_list_lock); | 1822 | spin_unlock(&journal->j_list_lock); |
1771 | jbd_unlock_bh_state(bh); | 1823 | jbd_unlock_bh_state(bh); |
1772 | spin_unlock(&journal->j_state_lock); | 1824 | write_unlock(&journal->j_state_lock); |
1773 | return ret; | 1825 | return ret; |
1774 | } else { | 1826 | } else { |
1775 | /* There is no currently-running transaction. So the | 1827 | /* There is no currently-running transaction. So the |
@@ -1783,7 +1835,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1783 | jbd2_journal_put_journal_head(jh); | 1835 | jbd2_journal_put_journal_head(jh); |
1784 | spin_unlock(&journal->j_list_lock); | 1836 | spin_unlock(&journal->j_list_lock); |
1785 | jbd_unlock_bh_state(bh); | 1837 | jbd_unlock_bh_state(bh); |
1786 | spin_unlock(&journal->j_state_lock); | 1838 | write_unlock(&journal->j_state_lock); |
1787 | return ret; | 1839 | return ret; |
1788 | } else { | 1840 | } else { |
1789 | /* The orphan record's transaction has | 1841 | /* The orphan record's transaction has |
@@ -1807,7 +1859,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) | |||
1807 | jbd2_journal_put_journal_head(jh); | 1859 | jbd2_journal_put_journal_head(jh); |
1808 | spin_unlock(&journal->j_list_lock); | 1860 | spin_unlock(&journal->j_list_lock); |
1809 | jbd_unlock_bh_state(bh); | 1861 | jbd_unlock_bh_state(bh); |
1810 | spin_unlock(&journal->j_state_lock); | 1862 | write_unlock(&journal->j_state_lock); |
1811 | return 0; | 1863 | return 0; |
1812 | } else { | 1864 | } else { |
1813 | /* Good, the buffer belongs to the running transaction. | 1865 | /* Good, the buffer belongs to the running transaction. |
@@ -1826,7 +1878,7 @@ zap_buffer: | |||
1826 | zap_buffer_no_jh: | 1878 | zap_buffer_no_jh: |
1827 | spin_unlock(&journal->j_list_lock); | 1879 | spin_unlock(&journal->j_list_lock); |
1828 | jbd_unlock_bh_state(bh); | 1880 | jbd_unlock_bh_state(bh); |
1829 | spin_unlock(&journal->j_state_lock); | 1881 | write_unlock(&journal->j_state_lock); |
1830 | zap_buffer_unlocked: | 1882 | zap_buffer_unlocked: |
1831 | clear_buffer_dirty(bh); | 1883 | clear_buffer_dirty(bh); |
1832 | J_ASSERT_BH(bh, !buffer_jbddirty(bh)); | 1884 | J_ASSERT_BH(bh, !buffer_jbddirty(bh)); |
@@ -2133,9 +2185,9 @@ int jbd2_journal_begin_ordered_truncate(journal_t *journal, | |||
2133 | /* Locks are here just to force reading of recent values, it is | 2185 | /* Locks are here just to force reading of recent values, it is |
2134 | * enough that the transaction was not committing before we started | 2186 | * enough that the transaction was not committing before we started |
2135 | * a transaction adding the inode to orphan list */ | 2187 | * a transaction adding the inode to orphan list */ |
2136 | spin_lock(&journal->j_state_lock); | 2188 | read_lock(&journal->j_state_lock); |
2137 | commit_trans = journal->j_committing_transaction; | 2189 | commit_trans = journal->j_committing_transaction; |
2138 | spin_unlock(&journal->j_state_lock); | 2190 | read_unlock(&journal->j_state_lock); |
2139 | spin_lock(&journal->j_list_lock); | 2191 | spin_lock(&journal->j_list_lock); |
2140 | inode_trans = jinode->i_transaction; | 2192 | inode_trans = jinode->i_transaction; |
2141 | spin_unlock(&journal->j_list_lock); | 2193 | spin_unlock(&journal->j_list_lock); |
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c index a2d58c96f1b4..d258e261bdc7 100644 --- a/fs/jffs2/xattr.c +++ b/fs/jffs2/xattr.c | |||
@@ -626,7 +626,7 @@ void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i | |||
626 | 626 | ||
627 | static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) | 627 | static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) |
628 | { | 628 | { |
629 | /* success of check_xattr_ref_inode() means taht inode (ic) dose not have | 629 | /* success of check_xattr_ref_inode() means that inode (ic) dose not have |
630 | * duplicate name/value pairs. If duplicate name/value pair would be found, | 630 | * duplicate name/value pairs. If duplicate name/value pair would be found, |
631 | * one will be removed. | 631 | * one will be removed. |
632 | */ | 632 | */ |
diff --git a/fs/mbcache.c b/fs/mbcache.c index ec88ff3d04a9..e28f21b95344 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c | |||
@@ -115,7 +115,7 @@ mb_cache_indexes(struct mb_cache *cache) | |||
115 | * What the mbcache registers as to get shrunk dynamically. | 115 | * What the mbcache registers as to get shrunk dynamically. |
116 | */ | 116 | */ |
117 | 117 | ||
118 | static int mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask); | 118 | static int mb_cache_shrink_fn(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask); |
119 | 119 | ||
120 | static struct shrinker mb_cache_shrinker = { | 120 | static struct shrinker mb_cache_shrinker = { |
121 | .shrink = mb_cache_shrink_fn, | 121 | .shrink = mb_cache_shrink_fn, |
@@ -191,13 +191,14 @@ forget: | |||
191 | * This function is called by the kernel memory management when memory | 191 | * This function is called by the kernel memory management when memory |
192 | * gets low. | 192 | * gets low. |
193 | * | 193 | * |
194 | * @shrink: (ignored) | ||
194 | * @nr_to_scan: Number of objects to scan | 195 | * @nr_to_scan: Number of objects to scan |
195 | * @gfp_mask: (ignored) | 196 | * @gfp_mask: (ignored) |
196 | * | 197 | * |
197 | * Returns the number of objects which are present in the cache. | 198 | * Returns the number of objects which are present in the cache. |
198 | */ | 199 | */ |
199 | static int | 200 | static int |
200 | mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask) | 201 | mb_cache_shrink_fn(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) |
201 | { | 202 | { |
202 | LIST_HEAD(free_list); | 203 | LIST_HEAD(free_list); |
203 | struct list_head *l, *ltmp; | 204 | struct list_head *l, *ltmp; |
diff --git a/fs/namei.c b/fs/namei.c index 868d0cb9d473..42d2d28fb827 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -282,8 +282,7 @@ int inode_permission(struct inode *inode, int mask) | |||
282 | if (retval) | 282 | if (retval) |
283 | return retval; | 283 | return retval; |
284 | 284 | ||
285 | return security_inode_permission(inode, | 285 | return security_inode_permission(inode, mask); |
286 | mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND)); | ||
287 | } | 286 | } |
288 | 287 | ||
289 | /** | 288 | /** |
@@ -1484,8 +1483,7 @@ static int handle_truncate(struct path *path) | |||
1484 | */ | 1483 | */ |
1485 | error = locks_verify_locked(inode); | 1484 | error = locks_verify_locked(inode); |
1486 | if (!error) | 1485 | if (!error) |
1487 | error = security_path_truncate(path, 0, | 1486 | error = security_path_truncate(path); |
1488 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN); | ||
1489 | if (!error) { | 1487 | if (!error) { |
1490 | error = do_truncate(path->dentry, 0, | 1488 | error = do_truncate(path->dentry, 0, |
1491 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, | 1489 | ATTR_MTIME|ATTR_CTIME|ATTR_OPEN, |
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index fa3385154023..1e634deff941 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c | |||
@@ -728,8 +728,8 @@ out_fput: | |||
728 | out_bdi: | 728 | out_bdi: |
729 | /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>: | 729 | /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>: |
730 | * | 730 | * |
731 | * The previously used put_filp(ncp_filp); was bogous, since | 731 | * The previously used put_filp(ncp_filp); was bogus, since |
732 | * it doesn't proper unlocking. | 732 | * it doesn't perform proper unlocking. |
733 | */ | 733 | */ |
734 | fput(ncp_filp); | 734 | fput(ncp_filp); |
735 | out: | 735 | out: |
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index a43d07e7b924..cc1bb33b59b8 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig | |||
@@ -61,8 +61,8 @@ config NFS_V3_ACL | |||
61 | If unsure, say N. | 61 | If unsure, say N. |
62 | 62 | ||
63 | config NFS_V4 | 63 | config NFS_V4 |
64 | bool "NFS client support for NFS version 4 (EXPERIMENTAL)" | 64 | bool "NFS client support for NFS version 4" |
65 | depends on NFS_FS && EXPERIMENTAL | 65 | depends on NFS_FS |
66 | select RPCSEC_GSS_KRB5 | 66 | select RPCSEC_GSS_KRB5 |
67 | help | 67 | help |
68 | This option enables support for version 4 of the NFS protocol | 68 | This option enables support for version 4 of the NFS protocol |
@@ -72,16 +72,16 @@ config NFS_V4 | |||
72 | space programs which can be found in the Linux nfs-utils package, | 72 | space programs which can be found in the Linux nfs-utils package, |
73 | available from http://linux-nfs.org/. | 73 | available from http://linux-nfs.org/. |
74 | 74 | ||
75 | If unsure, say N. | 75 | If unsure, say Y. |
76 | 76 | ||
77 | config NFS_V4_1 | 77 | config NFS_V4_1 |
78 | bool "NFS client support for NFSv4.1 (DEVELOPER ONLY)" | 78 | bool "NFS client support for NFSv4.1 (EXPERIMENTAL)" |
79 | depends on NFS_V4 && EXPERIMENTAL | 79 | depends on NFS_V4 && EXPERIMENTAL |
80 | help | 80 | help |
81 | This option enables support for minor version 1 of the NFSv4 protocol | 81 | This option enables support for minor version 1 of the NFSv4 protocol |
82 | (draft-ietf-nfsv4-minorversion1) in the kernel's NFS client. | 82 | (draft-ietf-nfsv4-minorversion1) in the kernel's NFS client. |
83 | 83 | ||
84 | Unless you're an NFS developer, say N. | 84 | If unsure, say N. |
85 | 85 | ||
86 | config ROOT_NFS | 86 | config ROOT_NFS |
87 | bool "Root file system on NFS" | 87 | bool "Root file system on NFS" |
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index a08770a7e857..930d10fecdaf 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c | |||
@@ -37,8 +37,8 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres * | |||
37 | if (inode == NULL) | 37 | if (inode == NULL) |
38 | goto out_putclient; | 38 | goto out_putclient; |
39 | nfsi = NFS_I(inode); | 39 | nfsi = NFS_I(inode); |
40 | down_read(&nfsi->rwsem); | 40 | rcu_read_lock(); |
41 | delegation = nfsi->delegation; | 41 | delegation = rcu_dereference(nfsi->delegation); |
42 | if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0) | 42 | if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0) |
43 | goto out_iput; | 43 | goto out_iput; |
44 | res->size = i_size_read(inode); | 44 | res->size = i_size_read(inode); |
@@ -53,7 +53,7 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres * | |||
53 | args->bitmap[1]; | 53 | args->bitmap[1]; |
54 | res->status = 0; | 54 | res->status = 0; |
55 | out_iput: | 55 | out_iput: |
56 | up_read(&nfsi->rwsem); | 56 | rcu_read_unlock(); |
57 | iput(inode); | 57 | iput(inode); |
58 | out_putclient: | 58 | out_putclient: |
59 | nfs_put_client(clp); | 59 | nfs_put_client(clp); |
@@ -62,16 +62,6 @@ out: | |||
62 | return res->status; | 62 | return res->status; |
63 | } | 63 | } |
64 | 64 | ||
65 | static int (*nfs_validate_delegation_stateid(struct nfs_client *clp))(struct nfs_delegation *, const nfs4_stateid *) | ||
66 | { | ||
67 | #if defined(CONFIG_NFS_V4_1) | ||
68 | if (clp->cl_minorversion > 0) | ||
69 | return nfs41_validate_delegation_stateid; | ||
70 | #endif | ||
71 | return nfs4_validate_delegation_stateid; | ||
72 | } | ||
73 | |||
74 | |||
75 | __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) | 65 | __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) |
76 | { | 66 | { |
77 | struct nfs_client *clp; | 67 | struct nfs_client *clp; |
@@ -92,8 +82,7 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy) | |||
92 | inode = nfs_delegation_find_inode(clp, &args->fh); | 82 | inode = nfs_delegation_find_inode(clp, &args->fh); |
93 | if (inode != NULL) { | 83 | if (inode != NULL) { |
94 | /* Set up a helper thread to actually return the delegation */ | 84 | /* Set up a helper thread to actually return the delegation */ |
95 | switch (nfs_async_inode_return_delegation(inode, &args->stateid, | 85 | switch (nfs_async_inode_return_delegation(inode, &args->stateid)) { |
96 | nfs_validate_delegation_stateid(clp))) { | ||
97 | case 0: | 86 | case 0: |
98 | res = 0; | 87 | res = 0; |
99 | break; | 88 | break; |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index d25b5257b7a1..4e7df2adb212 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -150,6 +150,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ | |||
150 | clp->cl_boot_time = CURRENT_TIME; | 150 | clp->cl_boot_time = CURRENT_TIME; |
151 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; | 151 | clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; |
152 | clp->cl_minorversion = cl_init->minorversion; | 152 | clp->cl_minorversion = cl_init->minorversion; |
153 | clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion]; | ||
153 | #endif | 154 | #endif |
154 | cred = rpc_lookup_machine_cred(); | 155 | cred = rpc_lookup_machine_cred(); |
155 | if (!IS_ERR(cred)) | 156 | if (!IS_ERR(cred)) |
@@ -178,7 +179,7 @@ static void nfs4_clear_client_minor_version(struct nfs_client *clp) | |||
178 | clp->cl_session = NULL; | 179 | clp->cl_session = NULL; |
179 | } | 180 | } |
180 | 181 | ||
181 | clp->cl_call_sync = _nfs4_call_sync; | 182 | clp->cl_mvops = nfs_v4_minor_ops[0]; |
182 | #endif /* CONFIG_NFS_V4_1 */ | 183 | #endif /* CONFIG_NFS_V4_1 */ |
183 | } | 184 | } |
184 | 185 | ||
@@ -188,7 +189,7 @@ static void nfs4_clear_client_minor_version(struct nfs_client *clp) | |||
188 | static void nfs4_destroy_callback(struct nfs_client *clp) | 189 | static void nfs4_destroy_callback(struct nfs_client *clp) |
189 | { | 190 | { |
190 | if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) | 191 | if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) |
191 | nfs_callback_down(clp->cl_minorversion); | 192 | nfs_callback_down(clp->cl_mvops->minor_version); |
192 | } | 193 | } |
193 | 194 | ||
194 | static void nfs4_shutdown_client(struct nfs_client *clp) | 195 | static void nfs4_shutdown_client(struct nfs_client *clp) |
@@ -1126,7 +1127,7 @@ static int nfs4_init_callback(struct nfs_client *clp) | |||
1126 | return error; | 1127 | return error; |
1127 | } | 1128 | } |
1128 | 1129 | ||
1129 | error = nfs_callback_up(clp->cl_minorversion, | 1130 | error = nfs_callback_up(clp->cl_mvops->minor_version, |
1130 | clp->cl_rpcclient->cl_xprt); | 1131 | clp->cl_rpcclient->cl_xprt); |
1131 | if (error < 0) { | 1132 | if (error < 0) { |
1132 | dprintk("%s: failed to start callback. Error = %d\n", | 1133 | dprintk("%s: failed to start callback. Error = %d\n", |
@@ -1143,10 +1144,8 @@ static int nfs4_init_callback(struct nfs_client *clp) | |||
1143 | */ | 1144 | */ |
1144 | static int nfs4_init_client_minor_version(struct nfs_client *clp) | 1145 | static int nfs4_init_client_minor_version(struct nfs_client *clp) |
1145 | { | 1146 | { |
1146 | clp->cl_call_sync = _nfs4_call_sync; | ||
1147 | |||
1148 | #if defined(CONFIG_NFS_V4_1) | 1147 | #if defined(CONFIG_NFS_V4_1) |
1149 | if (clp->cl_minorversion) { | 1148 | if (clp->cl_mvops->minor_version) { |
1150 | struct nfs4_session *session = NULL; | 1149 | struct nfs4_session *session = NULL; |
1151 | /* | 1150 | /* |
1152 | * Create the session and mark it expired. | 1151 | * Create the session and mark it expired. |
@@ -1158,7 +1157,13 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp) | |||
1158 | return -ENOMEM; | 1157 | return -ENOMEM; |
1159 | 1158 | ||
1160 | clp->cl_session = session; | 1159 | clp->cl_session = session; |
1161 | clp->cl_call_sync = _nfs4_call_sync_session; | 1160 | /* |
1161 | * The create session reply races with the server back | ||
1162 | * channel probe. Mark the client NFS_CS_SESSION_INITING | ||
1163 | * so that the client back channel can find the | ||
1164 | * nfs_client struct | ||
1165 | */ | ||
1166 | clp->cl_cons_state = NFS_CS_SESSION_INITING; | ||
1162 | } | 1167 | } |
1163 | #endif /* CONFIG_NFS_V4_1 */ | 1168 | #endif /* CONFIG_NFS_V4_1 */ |
1164 | 1169 | ||
@@ -1454,7 +1459,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1454 | data->authflavor, | 1459 | data->authflavor, |
1455 | parent_server->client->cl_xprt->prot, | 1460 | parent_server->client->cl_xprt->prot, |
1456 | parent_server->client->cl_timeout, | 1461 | parent_server->client->cl_timeout, |
1457 | parent_client->cl_minorversion); | 1462 | parent_client->cl_mvops->minor_version); |
1458 | if (error < 0) | 1463 | if (error < 0) |
1459 | goto error; | 1464 | goto error; |
1460 | 1465 | ||
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 301634543974..b9c3c43cea1d 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -268,14 +268,6 @@ out: | |||
268 | return status; | 268 | return status; |
269 | } | 269 | } |
270 | 270 | ||
271 | /* Sync all data to disk upon delegation return */ | ||
272 | static void nfs_msync_inode(struct inode *inode) | ||
273 | { | ||
274 | filemap_fdatawrite(inode->i_mapping); | ||
275 | nfs_wb_all(inode); | ||
276 | filemap_fdatawait(inode->i_mapping); | ||
277 | } | ||
278 | |||
279 | /* | 271 | /* |
280 | * Basic procedure for returning a delegation to the server | 272 | * Basic procedure for returning a delegation to the server |
281 | */ | 273 | */ |
@@ -367,7 +359,7 @@ int nfs_inode_return_delegation(struct inode *inode) | |||
367 | delegation = nfs_detach_delegation_locked(nfsi, NULL, clp); | 359 | delegation = nfs_detach_delegation_locked(nfsi, NULL, clp); |
368 | spin_unlock(&clp->cl_lock); | 360 | spin_unlock(&clp->cl_lock); |
369 | if (delegation != NULL) { | 361 | if (delegation != NULL) { |
370 | nfs_msync_inode(inode); | 362 | nfs_wb_all(inode); |
371 | err = __nfs_inode_return_delegation(inode, delegation, 1); | 363 | err = __nfs_inode_return_delegation(inode, delegation, 1); |
372 | } | 364 | } |
373 | } | 365 | } |
@@ -471,9 +463,7 @@ void nfs_expire_unreferenced_delegations(struct nfs_client *clp) | |||
471 | /* | 463 | /* |
472 | * Asynchronous delegation recall! | 464 | * Asynchronous delegation recall! |
473 | */ | 465 | */ |
474 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid, | 466 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid) |
475 | int (*validate_stateid)(struct nfs_delegation *delegation, | ||
476 | const nfs4_stateid *stateid)) | ||
477 | { | 467 | { |
478 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; | 468 | struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; |
479 | struct nfs_delegation *delegation; | 469 | struct nfs_delegation *delegation; |
@@ -481,7 +471,7 @@ int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *s | |||
481 | rcu_read_lock(); | 471 | rcu_read_lock(); |
482 | delegation = rcu_dereference(NFS_I(inode)->delegation); | 472 | delegation = rcu_dereference(NFS_I(inode)->delegation); |
483 | 473 | ||
484 | if (!validate_stateid(delegation, stateid)) { | 474 | if (!clp->cl_mvops->validate_stateid(delegation, stateid)) { |
485 | rcu_read_unlock(); | 475 | rcu_read_unlock(); |
486 | return -ENOENT; | 476 | return -ENOENT; |
487 | } | 477 | } |
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 69e7b8140122..2026304bda19 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h | |||
@@ -34,9 +34,7 @@ enum { | |||
34 | int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); | 34 | int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); |
35 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); | 35 | void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); |
36 | int nfs_inode_return_delegation(struct inode *inode); | 36 | int nfs_inode_return_delegation(struct inode *inode); |
37 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid, | 37 | int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid); |
38 | int (*validate_stateid)(struct nfs_delegation *delegation, | ||
39 | const nfs4_stateid *stateid)); | ||
40 | void nfs_inode_return_delegation_noreclaim(struct inode *inode); | 38 | void nfs_inode_return_delegation_noreclaim(struct inode *inode); |
41 | 39 | ||
42 | struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle); | 40 | struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle); |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 782b431ef91c..29539ceeb745 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1652,16 +1652,7 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1652 | } | 1652 | } |
1653 | } | 1653 | } |
1654 | 1654 | ||
1655 | /* | ||
1656 | * ... prune child dentries and writebacks if needed. | ||
1657 | */ | ||
1658 | if (atomic_read(&old_dentry->d_count) > 1) { | ||
1659 | if (S_ISREG(old_inode->i_mode)) | ||
1660 | nfs_wb_all(old_inode); | ||
1661 | shrink_dcache_parent(old_dentry); | ||
1662 | } | ||
1663 | nfs_inode_return_delegation(old_inode); | 1655 | nfs_inode_return_delegation(old_inode); |
1664 | |||
1665 | if (new_inode != NULL) | 1656 | if (new_inode != NULL) |
1666 | nfs_inode_return_delegation(new_inode); | 1657 | nfs_inode_return_delegation(new_inode); |
1667 | 1658 | ||
@@ -1710,7 +1701,7 @@ static void nfs_access_free_list(struct list_head *head) | |||
1710 | } | 1701 | } |
1711 | } | 1702 | } |
1712 | 1703 | ||
1713 | int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask) | 1704 | int nfs_access_cache_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) |
1714 | { | 1705 | { |
1715 | LIST_HEAD(head); | 1706 | LIST_HEAD(head); |
1716 | struct nfs_inode *nfsi; | 1707 | struct nfs_inode *nfsi; |
@@ -1953,7 +1944,7 @@ int nfs_permission(struct inode *inode, int mask) | |||
1953 | if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) | 1944 | if ((mask & (MAY_READ | MAY_WRITE | MAY_EXEC)) == 0) |
1954 | goto out; | 1945 | goto out; |
1955 | /* Is this sys_access() ? */ | 1946 | /* Is this sys_access() ? */ |
1956 | if (mask & MAY_ACCESS) | 1947 | if (mask & (MAY_ACCESS | MAY_CHDIR)) |
1957 | goto force_lookup; | 1948 | goto force_lookup; |
1958 | 1949 | ||
1959 | switch (inode->i_mode & S_IFMT) { | 1950 | switch (inode->i_mode & S_IFMT) { |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index ad4cd31d6050..064a80961677 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -69,6 +69,7 @@ struct nfs_direct_req { | |||
69 | 69 | ||
70 | /* I/O parameters */ | 70 | /* I/O parameters */ |
71 | struct nfs_open_context *ctx; /* file open context info */ | 71 | struct nfs_open_context *ctx; /* file open context info */ |
72 | struct nfs_lock_context *l_ctx; /* Lock context info */ | ||
72 | struct kiocb * iocb; /* controlling i/o request */ | 73 | struct kiocb * iocb; /* controlling i/o request */ |
73 | struct inode * inode; /* target file of i/o */ | 74 | struct inode * inode; /* target file of i/o */ |
74 | 75 | ||
@@ -160,6 +161,7 @@ static inline struct nfs_direct_req *nfs_direct_req_alloc(void) | |||
160 | INIT_LIST_HEAD(&dreq->rewrite_list); | 161 | INIT_LIST_HEAD(&dreq->rewrite_list); |
161 | dreq->iocb = NULL; | 162 | dreq->iocb = NULL; |
162 | dreq->ctx = NULL; | 163 | dreq->ctx = NULL; |
164 | dreq->l_ctx = NULL; | ||
163 | spin_lock_init(&dreq->lock); | 165 | spin_lock_init(&dreq->lock); |
164 | atomic_set(&dreq->io_count, 0); | 166 | atomic_set(&dreq->io_count, 0); |
165 | dreq->count = 0; | 167 | dreq->count = 0; |
@@ -173,6 +175,8 @@ static void nfs_direct_req_free(struct kref *kref) | |||
173 | { | 175 | { |
174 | struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); | 176 | struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref); |
175 | 177 | ||
178 | if (dreq->l_ctx != NULL) | ||
179 | nfs_put_lock_context(dreq->l_ctx); | ||
176 | if (dreq->ctx != NULL) | 180 | if (dreq->ctx != NULL) |
177 | put_nfs_open_context(dreq->ctx); | 181 | put_nfs_open_context(dreq->ctx); |
178 | kmem_cache_free(nfs_direct_cachep, dreq); | 182 | kmem_cache_free(nfs_direct_cachep, dreq); |
@@ -336,6 +340,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
336 | data->cred = msg.rpc_cred; | 340 | data->cred = msg.rpc_cred; |
337 | data->args.fh = NFS_FH(inode); | 341 | data->args.fh = NFS_FH(inode); |
338 | data->args.context = ctx; | 342 | data->args.context = ctx; |
343 | data->args.lock_context = dreq->l_ctx; | ||
339 | data->args.offset = pos; | 344 | data->args.offset = pos; |
340 | data->args.pgbase = pgbase; | 345 | data->args.pgbase = pgbase; |
341 | data->args.pages = data->pagevec; | 346 | data->args.pages = data->pagevec; |
@@ -416,24 +421,28 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | |||
416 | static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, | 421 | static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, |
417 | unsigned long nr_segs, loff_t pos) | 422 | unsigned long nr_segs, loff_t pos) |
418 | { | 423 | { |
419 | ssize_t result = 0; | 424 | ssize_t result = -ENOMEM; |
420 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 425 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
421 | struct nfs_direct_req *dreq; | 426 | struct nfs_direct_req *dreq; |
422 | 427 | ||
423 | dreq = nfs_direct_req_alloc(); | 428 | dreq = nfs_direct_req_alloc(); |
424 | if (!dreq) | 429 | if (dreq == NULL) |
425 | return -ENOMEM; | 430 | goto out; |
426 | 431 | ||
427 | dreq->inode = inode; | 432 | dreq->inode = inode; |
428 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 433 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
434 | dreq->l_ctx = nfs_get_lock_context(dreq->ctx); | ||
435 | if (dreq->l_ctx == NULL) | ||
436 | goto out_release; | ||
429 | if (!is_sync_kiocb(iocb)) | 437 | if (!is_sync_kiocb(iocb)) |
430 | dreq->iocb = iocb; | 438 | dreq->iocb = iocb; |
431 | 439 | ||
432 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); | 440 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); |
433 | if (!result) | 441 | if (!result) |
434 | result = nfs_direct_wait(dreq); | 442 | result = nfs_direct_wait(dreq); |
443 | out_release: | ||
435 | nfs_direct_req_release(dreq); | 444 | nfs_direct_req_release(dreq); |
436 | 445 | out: | |
437 | return result; | 446 | return result; |
438 | } | 447 | } |
439 | 448 | ||
@@ -574,6 +583,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | |||
574 | data->args.offset = 0; | 583 | data->args.offset = 0; |
575 | data->args.count = 0; | 584 | data->args.count = 0; |
576 | data->args.context = dreq->ctx; | 585 | data->args.context = dreq->ctx; |
586 | data->args.lock_context = dreq->l_ctx; | ||
577 | data->res.count = 0; | 587 | data->res.count = 0; |
578 | data->res.fattr = &data->fattr; | 588 | data->res.fattr = &data->fattr; |
579 | data->res.verf = &data->verf; | 589 | data->res.verf = &data->verf; |
@@ -761,6 +771,7 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
761 | data->cred = msg.rpc_cred; | 771 | data->cred = msg.rpc_cred; |
762 | data->args.fh = NFS_FH(inode); | 772 | data->args.fh = NFS_FH(inode); |
763 | data->args.context = ctx; | 773 | data->args.context = ctx; |
774 | data->args.lock_context = dreq->l_ctx; | ||
764 | data->args.offset = pos; | 775 | data->args.offset = pos; |
765 | data->args.pgbase = pgbase; | 776 | data->args.pgbase = pgbase; |
766 | data->args.pages = data->pagevec; | 777 | data->args.pages = data->pagevec; |
@@ -845,7 +856,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
845 | unsigned long nr_segs, loff_t pos, | 856 | unsigned long nr_segs, loff_t pos, |
846 | size_t count) | 857 | size_t count) |
847 | { | 858 | { |
848 | ssize_t result = 0; | 859 | ssize_t result = -ENOMEM; |
849 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 860 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
850 | struct nfs_direct_req *dreq; | 861 | struct nfs_direct_req *dreq; |
851 | size_t wsize = NFS_SERVER(inode)->wsize; | 862 | size_t wsize = NFS_SERVER(inode)->wsize; |
@@ -853,7 +864,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
853 | 864 | ||
854 | dreq = nfs_direct_req_alloc(); | 865 | dreq = nfs_direct_req_alloc(); |
855 | if (!dreq) | 866 | if (!dreq) |
856 | return -ENOMEM; | 867 | goto out; |
857 | nfs_alloc_commit_data(dreq); | 868 | nfs_alloc_commit_data(dreq); |
858 | 869 | ||
859 | if (dreq->commit_data == NULL || count < wsize) | 870 | if (dreq->commit_data == NULL || count < wsize) |
@@ -861,14 +872,18 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
861 | 872 | ||
862 | dreq->inode = inode; | 873 | dreq->inode = inode; |
863 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 874 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
875 | dreq->l_ctx = nfs_get_lock_context(dreq->ctx); | ||
876 | if (dreq->l_ctx != NULL) | ||
877 | goto out_release; | ||
864 | if (!is_sync_kiocb(iocb)) | 878 | if (!is_sync_kiocb(iocb)) |
865 | dreq->iocb = iocb; | 879 | dreq->iocb = iocb; |
866 | 880 | ||
867 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); | 881 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); |
868 | if (!result) | 882 | if (!result) |
869 | result = nfs_direct_wait(dreq); | 883 | result = nfs_direct_wait(dreq); |
884 | out_release: | ||
870 | nfs_direct_req_release(dreq); | 885 | nfs_direct_req_release(dreq); |
871 | 886 | out: | |
872 | return result; | 887 | return result; |
873 | } | 888 | } |
874 | 889 | ||
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 36a5e74f51b4..2d141a74ae82 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pagemap.h> | 27 | #include <linux/pagemap.h> |
28 | #include <linux/aio.h> | 28 | #include <linux/aio.h> |
29 | #include <linux/gfp.h> | 29 | #include <linux/gfp.h> |
30 | #include <linux/swap.h> | ||
30 | 31 | ||
31 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
32 | #include <asm/system.h> | 33 | #include <asm/system.h> |
@@ -202,37 +203,11 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | |||
202 | } | 203 | } |
203 | 204 | ||
204 | /* | 205 | /* |
205 | * Helper for nfs_file_flush() and nfs_file_fsync() | ||
206 | * | ||
207 | * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to | ||
208 | * disk, but it retrieves and clears ctx->error after synching, despite | ||
209 | * the two being set at the same time in nfs_context_set_write_error(). | ||
210 | * This is because the former is used to notify the _next_ call to | ||
211 | * nfs_file_write() that a write error occured, and hence cause it to | ||
212 | * fall back to doing a synchronous write. | ||
213 | */ | ||
214 | static int nfs_do_fsync(struct nfs_open_context *ctx, struct inode *inode) | ||
215 | { | ||
216 | int have_error, status; | ||
217 | int ret = 0; | ||
218 | |||
219 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
220 | status = nfs_wb_all(inode); | ||
221 | have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
222 | if (have_error) | ||
223 | ret = xchg(&ctx->error, 0); | ||
224 | if (!ret) | ||
225 | ret = status; | ||
226 | return ret; | ||
227 | } | ||
228 | |||
229 | /* | ||
230 | * Flush all dirty pages, and check for write errors. | 206 | * Flush all dirty pages, and check for write errors. |
231 | */ | 207 | */ |
232 | static int | 208 | static int |
233 | nfs_file_flush(struct file *file, fl_owner_t id) | 209 | nfs_file_flush(struct file *file, fl_owner_t id) |
234 | { | 210 | { |
235 | struct nfs_open_context *ctx = nfs_file_open_context(file); | ||
236 | struct dentry *dentry = file->f_path.dentry; | 211 | struct dentry *dentry = file->f_path.dentry; |
237 | struct inode *inode = dentry->d_inode; | 212 | struct inode *inode = dentry->d_inode; |
238 | 213 | ||
@@ -245,7 +220,7 @@ nfs_file_flush(struct file *file, fl_owner_t id) | |||
245 | return 0; | 220 | return 0; |
246 | 221 | ||
247 | /* Flush writes to the server and return any errors */ | 222 | /* Flush writes to the server and return any errors */ |
248 | return nfs_do_fsync(ctx, inode); | 223 | return vfs_fsync(file, 0); |
249 | } | 224 | } |
250 | 225 | ||
251 | static ssize_t | 226 | static ssize_t |
@@ -320,6 +295,13 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
320 | * Flush any dirty pages for this process, and check for write errors. | 295 | * Flush any dirty pages for this process, and check for write errors. |
321 | * The return status from this call provides a reliable indication of | 296 | * The return status from this call provides a reliable indication of |
322 | * whether any write errors occurred for this process. | 297 | * whether any write errors occurred for this process. |
298 | * | ||
299 | * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to | ||
300 | * disk, but it retrieves and clears ctx->error after synching, despite | ||
301 | * the two being set at the same time in nfs_context_set_write_error(). | ||
302 | * This is because the former is used to notify the _next_ call to | ||
303 | * nfs_file_write() that a write error occured, and hence cause it to | ||
304 | * fall back to doing a synchronous write. | ||
323 | */ | 305 | */ |
324 | static int | 306 | static int |
325 | nfs_file_fsync(struct file *file, int datasync) | 307 | nfs_file_fsync(struct file *file, int datasync) |
@@ -327,13 +309,23 @@ nfs_file_fsync(struct file *file, int datasync) | |||
327 | struct dentry *dentry = file->f_path.dentry; | 309 | struct dentry *dentry = file->f_path.dentry; |
328 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 310 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
329 | struct inode *inode = dentry->d_inode; | 311 | struct inode *inode = dentry->d_inode; |
312 | int have_error, status; | ||
313 | int ret = 0; | ||
314 | |||
330 | 315 | ||
331 | dprintk("NFS: fsync file(%s/%s) datasync %d\n", | 316 | dprintk("NFS: fsync file(%s/%s) datasync %d\n", |
332 | dentry->d_parent->d_name.name, dentry->d_name.name, | 317 | dentry->d_parent->d_name.name, dentry->d_name.name, |
333 | datasync); | 318 | datasync); |
334 | 319 | ||
335 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); | 320 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); |
336 | return nfs_do_fsync(ctx, inode); | 321 | have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); |
322 | status = nfs_commit_inode(inode, FLUSH_SYNC); | ||
323 | have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); | ||
324 | if (have_error) | ||
325 | ret = xchg(&ctx->error, 0); | ||
326 | if (!ret) | ||
327 | ret = status; | ||
328 | return ret; | ||
337 | } | 329 | } |
338 | 330 | ||
339 | /* | 331 | /* |
@@ -493,11 +485,19 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) | |||
493 | */ | 485 | */ |
494 | static int nfs_release_page(struct page *page, gfp_t gfp) | 486 | static int nfs_release_page(struct page *page, gfp_t gfp) |
495 | { | 487 | { |
488 | struct address_space *mapping = page->mapping; | ||
489 | |||
496 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); | 490 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); |
497 | 491 | ||
498 | /* Only do I/O if gfp is a superset of GFP_KERNEL */ | 492 | /* Only do I/O if gfp is a superset of GFP_KERNEL */ |
499 | if ((gfp & GFP_KERNEL) == GFP_KERNEL) | 493 | if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) { |
500 | nfs_wb_page(page->mapping->host, page); | 494 | int how = FLUSH_SYNC; |
495 | |||
496 | /* Don't let kswapd deadlock waiting for OOM RPC calls */ | ||
497 | if (current_is_kswapd()) | ||
498 | how = 0; | ||
499 | nfs_commit_inode(mapping->host, how); | ||
500 | } | ||
501 | /* If PagePrivate() is set, then the page is not freeable */ | 501 | /* If PagePrivate() is set, then the page is not freeable */ |
502 | if (PagePrivate(page)) | 502 | if (PagePrivate(page)) |
503 | return 0; | 503 | return 0; |
@@ -639,7 +639,7 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
639 | 639 | ||
640 | /* Return error values for O_DSYNC and IS_SYNC() */ | 640 | /* Return error values for O_DSYNC and IS_SYNC() */ |
641 | if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { | 641 | if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { |
642 | int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode); | 642 | int err = vfs_fsync(iocb->ki_filp, 0); |
643 | if (err < 0) | 643 | if (err < 0) |
644 | result = err; | 644 | result = err; |
645 | } | 645 | } |
@@ -675,7 +675,7 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, | |||
675 | written = ret; | 675 | written = ret; |
676 | 676 | ||
677 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { | 677 | if (ret >= 0 && nfs_need_sync_write(filp, inode)) { |
678 | int err = nfs_do_fsync(nfs_file_open_context(filp), inode); | 678 | int err = vfs_fsync(filp, 0); |
679 | if (err < 0) | 679 | if (err < 0) |
680 | ret = err; | 680 | ret = err; |
681 | } | 681 | } |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 099b3518feea..581d8f081e68 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -413,10 +413,8 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
413 | return 0; | 413 | return 0; |
414 | 414 | ||
415 | /* Write all dirty data */ | 415 | /* Write all dirty data */ |
416 | if (S_ISREG(inode->i_mode)) { | 416 | if (S_ISREG(inode->i_mode)) |
417 | filemap_write_and_wait(inode->i_mapping); | ||
418 | nfs_wb_all(inode); | 417 | nfs_wb_all(inode); |
419 | } | ||
420 | 418 | ||
421 | fattr = nfs_alloc_fattr(); | 419 | fattr = nfs_alloc_fattr(); |
422 | if (fattr == NULL) | 420 | if (fattr == NULL) |
@@ -530,6 +528,68 @@ out: | |||
530 | return err; | 528 | return err; |
531 | } | 529 | } |
532 | 530 | ||
531 | static void nfs_init_lock_context(struct nfs_lock_context *l_ctx) | ||
532 | { | ||
533 | atomic_set(&l_ctx->count, 1); | ||
534 | l_ctx->lockowner = current->files; | ||
535 | l_ctx->pid = current->tgid; | ||
536 | INIT_LIST_HEAD(&l_ctx->list); | ||
537 | } | ||
538 | |||
539 | static struct nfs_lock_context *__nfs_find_lock_context(struct nfs_open_context *ctx) | ||
540 | { | ||
541 | struct nfs_lock_context *pos; | ||
542 | |||
543 | list_for_each_entry(pos, &ctx->lock_context.list, list) { | ||
544 | if (pos->lockowner != current->files) | ||
545 | continue; | ||
546 | if (pos->pid != current->tgid) | ||
547 | continue; | ||
548 | atomic_inc(&pos->count); | ||
549 | return pos; | ||
550 | } | ||
551 | return NULL; | ||
552 | } | ||
553 | |||
554 | struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx) | ||
555 | { | ||
556 | struct nfs_lock_context *res, *new = NULL; | ||
557 | struct inode *inode = ctx->path.dentry->d_inode; | ||
558 | |||
559 | spin_lock(&inode->i_lock); | ||
560 | res = __nfs_find_lock_context(ctx); | ||
561 | if (res == NULL) { | ||
562 | spin_unlock(&inode->i_lock); | ||
563 | new = kmalloc(sizeof(*new), GFP_KERNEL); | ||
564 | if (new == NULL) | ||
565 | return NULL; | ||
566 | nfs_init_lock_context(new); | ||
567 | spin_lock(&inode->i_lock); | ||
568 | res = __nfs_find_lock_context(ctx); | ||
569 | if (res == NULL) { | ||
570 | list_add_tail(&new->list, &ctx->lock_context.list); | ||
571 | new->open_context = ctx; | ||
572 | res = new; | ||
573 | new = NULL; | ||
574 | } | ||
575 | } | ||
576 | spin_unlock(&inode->i_lock); | ||
577 | kfree(new); | ||
578 | return res; | ||
579 | } | ||
580 | |||
581 | void nfs_put_lock_context(struct nfs_lock_context *l_ctx) | ||
582 | { | ||
583 | struct nfs_open_context *ctx = l_ctx->open_context; | ||
584 | struct inode *inode = ctx->path.dentry->d_inode; | ||
585 | |||
586 | if (!atomic_dec_and_lock(&l_ctx->count, &inode->i_lock)) | ||
587 | return; | ||
588 | list_del(&l_ctx->list); | ||
589 | spin_unlock(&inode->i_lock); | ||
590 | kfree(l_ctx); | ||
591 | } | ||
592 | |||
533 | /** | 593 | /** |
534 | * nfs_close_context - Common close_context() routine NFSv2/v3 | 594 | * nfs_close_context - Common close_context() routine NFSv2/v3 |
535 | * @ctx: pointer to context | 595 | * @ctx: pointer to context |
@@ -566,11 +626,11 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct | |||
566 | path_get(&ctx->path); | 626 | path_get(&ctx->path); |
567 | ctx->cred = get_rpccred(cred); | 627 | ctx->cred = get_rpccred(cred); |
568 | ctx->state = NULL; | 628 | ctx->state = NULL; |
569 | ctx->lockowner = current->files; | ||
570 | ctx->flags = 0; | 629 | ctx->flags = 0; |
571 | ctx->error = 0; | 630 | ctx->error = 0; |
572 | ctx->dir_cookie = 0; | 631 | ctx->dir_cookie = 0; |
573 | atomic_set(&ctx->count, 1); | 632 | nfs_init_lock_context(&ctx->lock_context); |
633 | ctx->lock_context.open_context = ctx; | ||
574 | } | 634 | } |
575 | return ctx; | 635 | return ctx; |
576 | } | 636 | } |
@@ -578,7 +638,7 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct | |||
578 | struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) | 638 | struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) |
579 | { | 639 | { |
580 | if (ctx != NULL) | 640 | if (ctx != NULL) |
581 | atomic_inc(&ctx->count); | 641 | atomic_inc(&ctx->lock_context.count); |
582 | return ctx; | 642 | return ctx; |
583 | } | 643 | } |
584 | 644 | ||
@@ -586,7 +646,7 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) | |||
586 | { | 646 | { |
587 | struct inode *inode = ctx->path.dentry->d_inode; | 647 | struct inode *inode = ctx->path.dentry->d_inode; |
588 | 648 | ||
589 | if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock)) | 649 | if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock)) |
590 | return; | 650 | return; |
591 | list_del(&ctx->list); | 651 | list_del(&ctx->list); |
592 | spin_unlock(&inode->i_lock); | 652 | spin_unlock(&inode->i_lock); |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index d8bd619e386c..4c2150d86714 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -205,7 +205,8 @@ extern struct rpc_procinfo nfs4_procedures[]; | |||
205 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); | 205 | void nfs_close_context(struct nfs_open_context *ctx, int is_sync); |
206 | 206 | ||
207 | /* dir.c */ | 207 | /* dir.c */ |
208 | extern int nfs_access_cache_shrinker(int nr_to_scan, gfp_t gfp_mask); | 208 | extern int nfs_access_cache_shrinker(struct shrinker *shrink, |
209 | int nr_to_scan, gfp_t gfp_mask); | ||
209 | 210 | ||
210 | /* inode.c */ | 211 | /* inode.c */ |
211 | extern struct workqueue_struct *nfsiod_workqueue; | 212 | extern struct workqueue_struct *nfsiod_workqueue; |
@@ -369,10 +370,9 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len) | |||
369 | * Helper for restarting RPC calls in the possible presence of NFSv4.1 | 370 | * Helper for restarting RPC calls in the possible presence of NFSv4.1 |
370 | * sessions. | 371 | * sessions. |
371 | */ | 372 | */ |
372 | static inline void nfs_restart_rpc(struct rpc_task *task, const struct nfs_client *clp) | 373 | static inline int nfs_restart_rpc(struct rpc_task *task, const struct nfs_client *clp) |
373 | { | 374 | { |
374 | if (nfs4_has_session(clp)) | 375 | if (nfs4_has_session(clp)) |
375 | rpc_restart_call_prepare(task); | 376 | return rpc_restart_call_prepare(task); |
376 | else | 377 | return rpc_restart_call(task); |
377 | rpc_restart_call(task); | ||
378 | } | 378 | } |
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 81cf14257916..db8846a0e82e 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
@@ -233,7 +233,7 @@ nfs_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs | |||
233 | static int | 233 | static int |
234 | nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) | 234 | nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) |
235 | { | 235 | { |
236 | struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; | 236 | struct rpc_auth *auth = req->rq_cred->cr_auth; |
237 | unsigned int replen; | 237 | unsigned int replen; |
238 | u32 offset = (u32)args->offset; | 238 | u32 offset = (u32)args->offset; |
239 | u32 count = args->count; | 239 | u32 count = args->count; |
@@ -393,8 +393,7 @@ nfs_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_symlinkargs *arg | |||
393 | static int | 393 | static int |
394 | nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args) | 394 | nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args) |
395 | { | 395 | { |
396 | struct rpc_task *task = req->rq_task; | 396 | struct rpc_auth *auth = req->rq_cred->cr_auth; |
397 | struct rpc_auth *auth = task->tk_msg.rpc_cred->cr_auth; | ||
398 | unsigned int replen; | 397 | unsigned int replen; |
399 | u32 count = args->count; | 398 | u32 count = args->count; |
400 | 399 | ||
@@ -575,7 +574,7 @@ nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res) | |||
575 | static int | 574 | static int |
576 | nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args) | 575 | nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args) |
577 | { | 576 | { |
578 | struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; | 577 | struct rpc_auth *auth = req->rq_cred->cr_auth; |
579 | unsigned int replen; | 578 | unsigned int replen; |
580 | 579 | ||
581 | p = xdr_encode_fhandle(p, args->fh); | 580 | p = xdr_encode_fhandle(p, args->fh); |
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 75dcfc7da365..9769704f8ce6 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -330,7 +330,7 @@ nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *arg | |||
330 | static int | 330 | static int |
331 | nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) | 331 | nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) |
332 | { | 332 | { |
333 | struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; | 333 | struct rpc_auth *auth = req->rq_cred->cr_auth; |
334 | unsigned int replen; | 334 | unsigned int replen; |
335 | u32 count = args->count; | 335 | u32 count = args->count; |
336 | 336 | ||
@@ -471,7 +471,7 @@ nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args) | |||
471 | static int | 471 | static int |
472 | nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args) | 472 | nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args) |
473 | { | 473 | { |
474 | struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; | 474 | struct rpc_auth *auth = req->rq_cred->cr_auth; |
475 | unsigned int replen; | 475 | unsigned int replen; |
476 | u32 count = args->count; | 476 | u32 count = args->count; |
477 | 477 | ||
@@ -675,7 +675,7 @@ static int | |||
675 | nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p, | 675 | nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p, |
676 | struct nfs3_getaclargs *args) | 676 | struct nfs3_getaclargs *args) |
677 | { | 677 | { |
678 | struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; | 678 | struct rpc_auth *auth = req->rq_cred->cr_auth; |
679 | unsigned int replen; | 679 | unsigned int replen; |
680 | 680 | ||
681 | p = xdr_encode_fhandle(p, args->fh); | 681 | p = xdr_encode_fhandle(p, args->fh); |
@@ -802,7 +802,7 @@ nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res) | |||
802 | static int | 802 | static int |
803 | nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args) | 803 | nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args) |
804 | { | 804 | { |
805 | struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; | 805 | struct rpc_auth *auth = req->rq_cred->cr_auth; |
806 | unsigned int replen; | 806 | unsigned int replen; |
807 | 807 | ||
808 | p = xdr_encode_fhandle(p, args->fh); | 808 | p = xdr_encode_fhandle(p, args->fh); |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index c538c6106e16..311e15cc8af0 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -45,10 +45,29 @@ enum nfs4_client_state { | |||
45 | NFS4CLNT_RECLAIM_NOGRACE, | 45 | NFS4CLNT_RECLAIM_NOGRACE, |
46 | NFS4CLNT_DELEGRETURN, | 46 | NFS4CLNT_DELEGRETURN, |
47 | NFS4CLNT_SESSION_RESET, | 47 | NFS4CLNT_SESSION_RESET, |
48 | NFS4CLNT_SESSION_DRAINING, | ||
49 | NFS4CLNT_RECALL_SLOT, | 48 | NFS4CLNT_RECALL_SLOT, |
50 | }; | 49 | }; |
51 | 50 | ||
51 | enum nfs4_session_state { | ||
52 | NFS4_SESSION_INITING, | ||
53 | NFS4_SESSION_DRAINING, | ||
54 | }; | ||
55 | |||
56 | struct nfs4_minor_version_ops { | ||
57 | u32 minor_version; | ||
58 | |||
59 | int (*call_sync)(struct nfs_server *server, | ||
60 | struct rpc_message *msg, | ||
61 | struct nfs4_sequence_args *args, | ||
62 | struct nfs4_sequence_res *res, | ||
63 | int cache_reply); | ||
64 | int (*validate_stateid)(struct nfs_delegation *, | ||
65 | const nfs4_stateid *); | ||
66 | const struct nfs4_state_recovery_ops *reboot_recovery_ops; | ||
67 | const struct nfs4_state_recovery_ops *nograce_recovery_ops; | ||
68 | const struct nfs4_state_maintenance_ops *state_renewal_ops; | ||
69 | }; | ||
70 | |||
52 | /* | 71 | /* |
53 | * struct rpc_sequence ensures that RPC calls are sent in the exact | 72 | * struct rpc_sequence ensures that RPC calls are sent in the exact |
54 | * order that they appear on the list. | 73 | * order that they appear on the list. |
@@ -89,7 +108,6 @@ struct nfs_unique_id { | |||
89 | */ | 108 | */ |
90 | struct nfs4_state_owner { | 109 | struct nfs4_state_owner { |
91 | struct nfs_unique_id so_owner_id; | 110 | struct nfs_unique_id so_owner_id; |
92 | struct nfs_client *so_client; | ||
93 | struct nfs_server *so_server; | 111 | struct nfs_server *so_server; |
94 | struct rb_node so_client_node; | 112 | struct rb_node so_client_node; |
95 | 113 | ||
@@ -99,7 +117,6 @@ struct nfs4_state_owner { | |||
99 | atomic_t so_count; | 117 | atomic_t so_count; |
100 | unsigned long so_flags; | 118 | unsigned long so_flags; |
101 | struct list_head so_states; | 119 | struct list_head so_states; |
102 | struct list_head so_delegations; | ||
103 | struct nfs_seqid_counter so_seqid; | 120 | struct nfs_seqid_counter so_seqid; |
104 | struct rpc_sequence so_sequence; | 121 | struct rpc_sequence so_sequence; |
105 | }; | 122 | }; |
@@ -125,10 +142,20 @@ enum { | |||
125 | * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN) | 142 | * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN) |
126 | */ | 143 | */ |
127 | 144 | ||
145 | struct nfs4_lock_owner { | ||
146 | unsigned int lo_type; | ||
147 | #define NFS4_ANY_LOCK_TYPE (0U) | ||
148 | #define NFS4_FLOCK_LOCK_TYPE (1U << 0) | ||
149 | #define NFS4_POSIX_LOCK_TYPE (1U << 1) | ||
150 | union { | ||
151 | fl_owner_t posix_owner; | ||
152 | pid_t flock_owner; | ||
153 | } lo_u; | ||
154 | }; | ||
155 | |||
128 | struct nfs4_lock_state { | 156 | struct nfs4_lock_state { |
129 | struct list_head ls_locks; /* Other lock stateids */ | 157 | struct list_head ls_locks; /* Other lock stateids */ |
130 | struct nfs4_state * ls_state; /* Pointer to open state */ | 158 | struct nfs4_state * ls_state; /* Pointer to open state */ |
131 | fl_owner_t ls_owner; /* POSIX lock owner */ | ||
132 | #define NFS_LOCK_INITIALIZED 1 | 159 | #define NFS_LOCK_INITIALIZED 1 |
133 | int ls_flags; | 160 | int ls_flags; |
134 | struct nfs_seqid_counter ls_seqid; | 161 | struct nfs_seqid_counter ls_seqid; |
@@ -136,6 +163,7 @@ struct nfs4_lock_state { | |||
136 | struct nfs_unique_id ls_id; | 163 | struct nfs_unique_id ls_id; |
137 | nfs4_stateid ls_stateid; | 164 | nfs4_stateid ls_stateid; |
138 | atomic_t ls_count; | 165 | atomic_t ls_count; |
166 | struct nfs4_lock_owner ls_owner; | ||
139 | }; | 167 | }; |
140 | 168 | ||
141 | /* bits for nfs4_state->flags */ | 169 | /* bits for nfs4_state->flags */ |
@@ -219,11 +247,15 @@ extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nam | |||
219 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); | 247 | extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle); |
220 | extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | 248 | extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, |
221 | struct nfs4_fs_locations *fs_locations, struct page *page); | 249 | struct nfs4_fs_locations *fs_locations, struct page *page); |
250 | extern void nfs4_release_lockowner(const struct nfs4_lock_state *); | ||
222 | 251 | ||
223 | extern struct nfs4_state_recovery_ops *nfs4_reboot_recovery_ops[]; | ||
224 | extern struct nfs4_state_recovery_ops *nfs4_nograce_recovery_ops[]; | ||
225 | #if defined(CONFIG_NFS_V4_1) | 252 | #if defined(CONFIG_NFS_V4_1) |
226 | extern int nfs4_setup_sequence(struct nfs_client *clp, | 253 | static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server) |
254 | { | ||
255 | return server->nfs_client->cl_session; | ||
256 | } | ||
257 | |||
258 | extern int nfs4_setup_sequence(const struct nfs_server *server, | ||
227 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | 259 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, |
228 | int cache_reply, struct rpc_task *task); | 260 | int cache_reply, struct rpc_task *task); |
229 | extern void nfs4_destroy_session(struct nfs4_session *session); | 261 | extern void nfs4_destroy_session(struct nfs4_session *session); |
@@ -234,7 +266,12 @@ extern int nfs4_init_session(struct nfs_server *server); | |||
234 | extern int nfs4_proc_get_lease_time(struct nfs_client *clp, | 266 | extern int nfs4_proc_get_lease_time(struct nfs_client *clp, |
235 | struct nfs_fsinfo *fsinfo); | 267 | struct nfs_fsinfo *fsinfo); |
236 | #else /* CONFIG_NFS_v4_1 */ | 268 | #else /* CONFIG_NFS_v4_1 */ |
237 | static inline int nfs4_setup_sequence(struct nfs_client *clp, | 269 | static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *server) |
270 | { | ||
271 | return NULL; | ||
272 | } | ||
273 | |||
274 | static inline int nfs4_setup_sequence(const struct nfs_server *server, | ||
238 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | 275 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, |
239 | int cache_reply, struct rpc_task *task) | 276 | int cache_reply, struct rpc_task *task) |
240 | { | 277 | { |
@@ -247,7 +284,7 @@ static inline int nfs4_init_session(struct nfs_server *server) | |||
247 | } | 284 | } |
248 | #endif /* CONFIG_NFS_V4_1 */ | 285 | #endif /* CONFIG_NFS_V4_1 */ |
249 | 286 | ||
250 | extern struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[]; | 287 | extern const struct nfs4_minor_version_ops *nfs_v4_minor_ops[]; |
251 | 288 | ||
252 | extern const u32 nfs4_fattr_bitmap[2]; | 289 | extern const u32 nfs4_fattr_bitmap[2]; |
253 | extern const u32 nfs4_statfs_bitmap[2]; | 290 | extern const u32 nfs4_statfs_bitmap[2]; |
@@ -284,7 +321,7 @@ extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) | |||
284 | extern void nfs41_handle_recall_slot(struct nfs_client *clp); | 321 | extern void nfs41_handle_recall_slot(struct nfs_client *clp); |
285 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); | 322 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); |
286 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); | 323 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); |
287 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); | 324 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t, pid_t); |
288 | 325 | ||
289 | extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask); | 326 | extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask); |
290 | extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); | 327 | extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 70015dd60a98..7ffbb98ddec3 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -303,15 +303,19 @@ do_state_recovery: | |||
303 | } | 303 | } |
304 | 304 | ||
305 | 305 | ||
306 | static void renew_lease(const struct nfs_server *server, unsigned long timestamp) | 306 | static void do_renew_lease(struct nfs_client *clp, unsigned long timestamp) |
307 | { | 307 | { |
308 | struct nfs_client *clp = server->nfs_client; | ||
309 | spin_lock(&clp->cl_lock); | 308 | spin_lock(&clp->cl_lock); |
310 | if (time_before(clp->cl_last_renewal,timestamp)) | 309 | if (time_before(clp->cl_last_renewal,timestamp)) |
311 | clp->cl_last_renewal = timestamp; | 310 | clp->cl_last_renewal = timestamp; |
312 | spin_unlock(&clp->cl_lock); | 311 | spin_unlock(&clp->cl_lock); |
313 | } | 312 | } |
314 | 313 | ||
314 | static void renew_lease(const struct nfs_server *server, unsigned long timestamp) | ||
315 | { | ||
316 | do_renew_lease(server->nfs_client, timestamp); | ||
317 | } | ||
318 | |||
315 | #if defined(CONFIG_NFS_V4_1) | 319 | #if defined(CONFIG_NFS_V4_1) |
316 | 320 | ||
317 | /* | 321 | /* |
@@ -356,7 +360,7 @@ static void nfs41_check_drain_session_complete(struct nfs4_session *ses) | |||
356 | { | 360 | { |
357 | struct rpc_task *task; | 361 | struct rpc_task *task; |
358 | 362 | ||
359 | if (!test_bit(NFS4CLNT_SESSION_DRAINING, &ses->clp->cl_state)) { | 363 | if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { |
360 | task = rpc_wake_up_next(&ses->fc_slot_table.slot_tbl_waitq); | 364 | task = rpc_wake_up_next(&ses->fc_slot_table.slot_tbl_waitq); |
361 | if (task) | 365 | if (task) |
362 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | 366 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); |
@@ -370,12 +374,11 @@ static void nfs41_check_drain_session_complete(struct nfs4_session *ses) | |||
370 | complete(&ses->complete); | 374 | complete(&ses->complete); |
371 | } | 375 | } |
372 | 376 | ||
373 | static void nfs41_sequence_free_slot(const struct nfs_client *clp, | 377 | static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) |
374 | struct nfs4_sequence_res *res) | ||
375 | { | 378 | { |
376 | struct nfs4_slot_table *tbl; | 379 | struct nfs4_slot_table *tbl; |
377 | 380 | ||
378 | tbl = &clp->cl_session->fc_slot_table; | 381 | tbl = &res->sr_session->fc_slot_table; |
379 | if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) { | 382 | if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) { |
380 | /* just wake up the next guy waiting since | 383 | /* just wake up the next guy waiting since |
381 | * we may have not consumed a slot after all */ | 384 | * we may have not consumed a slot after all */ |
@@ -385,18 +388,17 @@ static void nfs41_sequence_free_slot(const struct nfs_client *clp, | |||
385 | 388 | ||
386 | spin_lock(&tbl->slot_tbl_lock); | 389 | spin_lock(&tbl->slot_tbl_lock); |
387 | nfs4_free_slot(tbl, res->sr_slotid); | 390 | nfs4_free_slot(tbl, res->sr_slotid); |
388 | nfs41_check_drain_session_complete(clp->cl_session); | 391 | nfs41_check_drain_session_complete(res->sr_session); |
389 | spin_unlock(&tbl->slot_tbl_lock); | 392 | spin_unlock(&tbl->slot_tbl_lock); |
390 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | 393 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; |
391 | } | 394 | } |
392 | 395 | ||
393 | static void nfs41_sequence_done(struct nfs_client *clp, | 396 | static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) |
394 | struct nfs4_sequence_res *res, | ||
395 | int rpc_status) | ||
396 | { | 397 | { |
397 | unsigned long timestamp; | 398 | unsigned long timestamp; |
398 | struct nfs4_slot_table *tbl; | 399 | struct nfs4_slot_table *tbl; |
399 | struct nfs4_slot *slot; | 400 | struct nfs4_slot *slot; |
401 | struct nfs_client *clp; | ||
400 | 402 | ||
401 | /* | 403 | /* |
402 | * sr_status remains 1 if an RPC level error occurred. The server | 404 | * sr_status remains 1 if an RPC level error occurred. The server |
@@ -411,25 +413,51 @@ static void nfs41_sequence_done(struct nfs_client *clp, | |||
411 | if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) | 413 | if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) |
412 | goto out; | 414 | goto out; |
413 | 415 | ||
416 | tbl = &res->sr_session->fc_slot_table; | ||
417 | slot = tbl->slots + res->sr_slotid; | ||
418 | |||
414 | /* Check the SEQUENCE operation status */ | 419 | /* Check the SEQUENCE operation status */ |
415 | if (res->sr_status == 0) { | 420 | switch (res->sr_status) { |
416 | tbl = &clp->cl_session->fc_slot_table; | 421 | case 0: |
417 | slot = tbl->slots + res->sr_slotid; | ||
418 | /* Update the slot's sequence and clientid lease timer */ | 422 | /* Update the slot's sequence and clientid lease timer */ |
419 | ++slot->seq_nr; | 423 | ++slot->seq_nr; |
420 | timestamp = res->sr_renewal_time; | 424 | timestamp = res->sr_renewal_time; |
421 | spin_lock(&clp->cl_lock); | 425 | clp = res->sr_session->clp; |
422 | if (time_before(clp->cl_last_renewal, timestamp)) | 426 | do_renew_lease(clp, timestamp); |
423 | clp->cl_last_renewal = timestamp; | ||
424 | spin_unlock(&clp->cl_lock); | ||
425 | /* Check sequence flags */ | 427 | /* Check sequence flags */ |
426 | if (atomic_read(&clp->cl_count) > 1) | 428 | if (atomic_read(&clp->cl_count) > 1) |
427 | nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); | 429 | nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); |
430 | break; | ||
431 | case -NFS4ERR_DELAY: | ||
432 | /* The server detected a resend of the RPC call and | ||
433 | * returned NFS4ERR_DELAY as per Section 2.10.6.2 | ||
434 | * of RFC5661. | ||
435 | */ | ||
436 | dprintk("%s: slot=%d seq=%d: Operation in progress\n", | ||
437 | __func__, res->sr_slotid, slot->seq_nr); | ||
438 | goto out_retry; | ||
439 | default: | ||
440 | /* Just update the slot sequence no. */ | ||
441 | ++slot->seq_nr; | ||
428 | } | 442 | } |
429 | out: | 443 | out: |
430 | /* The session may be reset by one of the error handlers. */ | 444 | /* The session may be reset by one of the error handlers. */ |
431 | dprintk("%s: Error %d free the slot \n", __func__, res->sr_status); | 445 | dprintk("%s: Error %d free the slot \n", __func__, res->sr_status); |
432 | nfs41_sequence_free_slot(clp, res); | 446 | nfs41_sequence_free_slot(res); |
447 | return 1; | ||
448 | out_retry: | ||
449 | if (!rpc_restart_call(task)) | ||
450 | goto out; | ||
451 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | ||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static int nfs4_sequence_done(struct rpc_task *task, | ||
456 | struct nfs4_sequence_res *res) | ||
457 | { | ||
458 | if (res->sr_session == NULL) | ||
459 | return 1; | ||
460 | return nfs41_sequence_done(task, res); | ||
433 | } | 461 | } |
434 | 462 | ||
435 | /* | 463 | /* |
@@ -480,12 +508,11 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
480 | if (res->sr_slotid != NFS4_MAX_SLOT_TABLE) | 508 | if (res->sr_slotid != NFS4_MAX_SLOT_TABLE) |
481 | return 0; | 509 | return 0; |
482 | 510 | ||
483 | memset(res, 0, sizeof(*res)); | ||
484 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | 511 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; |
485 | tbl = &session->fc_slot_table; | 512 | tbl = &session->fc_slot_table; |
486 | 513 | ||
487 | spin_lock(&tbl->slot_tbl_lock); | 514 | spin_lock(&tbl->slot_tbl_lock); |
488 | if (test_bit(NFS4CLNT_SESSION_DRAINING, &session->clp->cl_state) && | 515 | if (test_bit(NFS4_SESSION_DRAINING, &session->session_state) && |
489 | !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) { | 516 | !rpc_task_has_priority(task, RPC_PRIORITY_PRIVILEGED)) { |
490 | /* | 517 | /* |
491 | * The state manager will wait until the slot table is empty. | 518 | * The state manager will wait until the slot table is empty. |
@@ -525,6 +552,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
525 | res->sr_session = session; | 552 | res->sr_session = session; |
526 | res->sr_slotid = slotid; | 553 | res->sr_slotid = slotid; |
527 | res->sr_renewal_time = jiffies; | 554 | res->sr_renewal_time = jiffies; |
555 | res->sr_status_flags = 0; | ||
528 | /* | 556 | /* |
529 | * sr_status is only set in decode_sequence, and so will remain | 557 | * sr_status is only set in decode_sequence, and so will remain |
530 | * set to 1 if an rpc level failure occurs. | 558 | * set to 1 if an rpc level failure occurs. |
@@ -533,33 +561,33 @@ static int nfs41_setup_sequence(struct nfs4_session *session, | |||
533 | return 0; | 561 | return 0; |
534 | } | 562 | } |
535 | 563 | ||
536 | int nfs4_setup_sequence(struct nfs_client *clp, | 564 | int nfs4_setup_sequence(const struct nfs_server *server, |
537 | struct nfs4_sequence_args *args, | 565 | struct nfs4_sequence_args *args, |
538 | struct nfs4_sequence_res *res, | 566 | struct nfs4_sequence_res *res, |
539 | int cache_reply, | 567 | int cache_reply, |
540 | struct rpc_task *task) | 568 | struct rpc_task *task) |
541 | { | 569 | { |
570 | struct nfs4_session *session = nfs4_get_session(server); | ||
542 | int ret = 0; | 571 | int ret = 0; |
543 | 572 | ||
573 | if (session == NULL) { | ||
574 | args->sa_session = NULL; | ||
575 | res->sr_session = NULL; | ||
576 | goto out; | ||
577 | } | ||
578 | |||
544 | dprintk("--> %s clp %p session %p sr_slotid %d\n", | 579 | dprintk("--> %s clp %p session %p sr_slotid %d\n", |
545 | __func__, clp, clp->cl_session, res->sr_slotid); | 580 | __func__, session->clp, session, res->sr_slotid); |
546 | 581 | ||
547 | if (!nfs4_has_session(clp)) | 582 | ret = nfs41_setup_sequence(session, args, res, cache_reply, |
548 | goto out; | ||
549 | ret = nfs41_setup_sequence(clp->cl_session, args, res, cache_reply, | ||
550 | task); | 583 | task); |
551 | if (ret && ret != -EAGAIN) { | ||
552 | /* terminate rpc task */ | ||
553 | task->tk_status = ret; | ||
554 | task->tk_action = NULL; | ||
555 | } | ||
556 | out: | 584 | out: |
557 | dprintk("<-- %s status=%d\n", __func__, ret); | 585 | dprintk("<-- %s status=%d\n", __func__, ret); |
558 | return ret; | 586 | return ret; |
559 | } | 587 | } |
560 | 588 | ||
561 | struct nfs41_call_sync_data { | 589 | struct nfs41_call_sync_data { |
562 | struct nfs_client *clp; | 590 | const struct nfs_server *seq_server; |
563 | struct nfs4_sequence_args *seq_args; | 591 | struct nfs4_sequence_args *seq_args; |
564 | struct nfs4_sequence_res *seq_res; | 592 | struct nfs4_sequence_res *seq_res; |
565 | int cache_reply; | 593 | int cache_reply; |
@@ -569,9 +597,9 @@ static void nfs41_call_sync_prepare(struct rpc_task *task, void *calldata) | |||
569 | { | 597 | { |
570 | struct nfs41_call_sync_data *data = calldata; | 598 | struct nfs41_call_sync_data *data = calldata; |
571 | 599 | ||
572 | dprintk("--> %s data->clp->cl_session %p\n", __func__, | 600 | dprintk("--> %s data->seq_server %p\n", __func__, data->seq_server); |
573 | data->clp->cl_session); | 601 | |
574 | if (nfs4_setup_sequence(data->clp, data->seq_args, | 602 | if (nfs4_setup_sequence(data->seq_server, data->seq_args, |
575 | data->seq_res, data->cache_reply, task)) | 603 | data->seq_res, data->cache_reply, task)) |
576 | return; | 604 | return; |
577 | rpc_call_start(task); | 605 | rpc_call_start(task); |
@@ -587,7 +615,7 @@ static void nfs41_call_sync_done(struct rpc_task *task, void *calldata) | |||
587 | { | 615 | { |
588 | struct nfs41_call_sync_data *data = calldata; | 616 | struct nfs41_call_sync_data *data = calldata; |
589 | 617 | ||
590 | nfs41_sequence_done(data->clp, data->seq_res, task->tk_status); | 618 | nfs41_sequence_done(task, data->seq_res); |
591 | } | 619 | } |
592 | 620 | ||
593 | struct rpc_call_ops nfs41_call_sync_ops = { | 621 | struct rpc_call_ops nfs41_call_sync_ops = { |
@@ -600,8 +628,7 @@ struct rpc_call_ops nfs41_call_priv_sync_ops = { | |||
600 | .rpc_call_done = nfs41_call_sync_done, | 628 | .rpc_call_done = nfs41_call_sync_done, |
601 | }; | 629 | }; |
602 | 630 | ||
603 | static int nfs4_call_sync_sequence(struct nfs_client *clp, | 631 | static int nfs4_call_sync_sequence(struct nfs_server *server, |
604 | struct rpc_clnt *clnt, | ||
605 | struct rpc_message *msg, | 632 | struct rpc_message *msg, |
606 | struct nfs4_sequence_args *args, | 633 | struct nfs4_sequence_args *args, |
607 | struct nfs4_sequence_res *res, | 634 | struct nfs4_sequence_res *res, |
@@ -611,13 +638,13 @@ static int nfs4_call_sync_sequence(struct nfs_client *clp, | |||
611 | int ret; | 638 | int ret; |
612 | struct rpc_task *task; | 639 | struct rpc_task *task; |
613 | struct nfs41_call_sync_data data = { | 640 | struct nfs41_call_sync_data data = { |
614 | .clp = clp, | 641 | .seq_server = server, |
615 | .seq_args = args, | 642 | .seq_args = args, |
616 | .seq_res = res, | 643 | .seq_res = res, |
617 | .cache_reply = cache_reply, | 644 | .cache_reply = cache_reply, |
618 | }; | 645 | }; |
619 | struct rpc_task_setup task_setup = { | 646 | struct rpc_task_setup task_setup = { |
620 | .rpc_client = clnt, | 647 | .rpc_client = server->client, |
621 | .rpc_message = msg, | 648 | .rpc_message = msg, |
622 | .callback_ops = &nfs41_call_sync_ops, | 649 | .callback_ops = &nfs41_call_sync_ops, |
623 | .callback_data = &data | 650 | .callback_data = &data |
@@ -642,10 +669,15 @@ int _nfs4_call_sync_session(struct nfs_server *server, | |||
642 | struct nfs4_sequence_res *res, | 669 | struct nfs4_sequence_res *res, |
643 | int cache_reply) | 670 | int cache_reply) |
644 | { | 671 | { |
645 | return nfs4_call_sync_sequence(server->nfs_client, server->client, | 672 | return nfs4_call_sync_sequence(server, msg, args, res, cache_reply, 0); |
646 | msg, args, res, cache_reply, 0); | ||
647 | } | 673 | } |
648 | 674 | ||
675 | #else | ||
676 | static int nfs4_sequence_done(struct rpc_task *task, | ||
677 | struct nfs4_sequence_res *res) | ||
678 | { | ||
679 | return 1; | ||
680 | } | ||
649 | #endif /* CONFIG_NFS_V4_1 */ | 681 | #endif /* CONFIG_NFS_V4_1 */ |
650 | 682 | ||
651 | int _nfs4_call_sync(struct nfs_server *server, | 683 | int _nfs4_call_sync(struct nfs_server *server, |
@@ -659,18 +691,9 @@ int _nfs4_call_sync(struct nfs_server *server, | |||
659 | } | 691 | } |
660 | 692 | ||
661 | #define nfs4_call_sync(server, msg, args, res, cache_reply) \ | 693 | #define nfs4_call_sync(server, msg, args, res, cache_reply) \ |
662 | (server)->nfs_client->cl_call_sync((server), (msg), &(args)->seq_args, \ | 694 | (server)->nfs_client->cl_mvops->call_sync((server), (msg), &(args)->seq_args, \ |
663 | &(res)->seq_res, (cache_reply)) | 695 | &(res)->seq_res, (cache_reply)) |
664 | 696 | ||
665 | static void nfs4_sequence_done(const struct nfs_server *server, | ||
666 | struct nfs4_sequence_res *res, int rpc_status) | ||
667 | { | ||
668 | #ifdef CONFIG_NFS_V4_1 | ||
669 | if (nfs4_has_session(server->nfs_client)) | ||
670 | nfs41_sequence_done(server->nfs_client, res, rpc_status); | ||
671 | #endif /* CONFIG_NFS_V4_1 */ | ||
672 | } | ||
673 | |||
674 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) | 697 | static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo) |
675 | { | 698 | { |
676 | struct nfs_inode *nfsi = NFS_I(dir); | 699 | struct nfs_inode *nfsi = NFS_I(dir); |
@@ -745,19 +768,14 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path, | |||
745 | p->o_arg.server = server; | 768 | p->o_arg.server = server; |
746 | p->o_arg.bitmask = server->attr_bitmask; | 769 | p->o_arg.bitmask = server->attr_bitmask; |
747 | p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; | 770 | p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; |
748 | if (flags & O_EXCL) { | 771 | if (flags & O_CREAT) { |
749 | if (nfs4_has_persistent_session(server->nfs_client)) { | 772 | u32 *s; |
750 | /* GUARDED */ | 773 | |
751 | p->o_arg.u.attrs = &p->attrs; | ||
752 | memcpy(&p->attrs, attrs, sizeof(p->attrs)); | ||
753 | } else { /* EXCLUSIVE4_1 */ | ||
754 | u32 *s = (u32 *) p->o_arg.u.verifier.data; | ||
755 | s[0] = jiffies; | ||
756 | s[1] = current->pid; | ||
757 | } | ||
758 | } else if (flags & O_CREAT) { | ||
759 | p->o_arg.u.attrs = &p->attrs; | 774 | p->o_arg.u.attrs = &p->attrs; |
760 | memcpy(&p->attrs, attrs, sizeof(p->attrs)); | 775 | memcpy(&p->attrs, attrs, sizeof(p->attrs)); |
776 | s = (u32 *) p->o_arg.u.verifier.data; | ||
777 | s[0] = jiffies; | ||
778 | s[1] = current->pid; | ||
761 | } | 779 | } |
762 | p->c_arg.fh = &p->o_res.fh; | 780 | p->c_arg.fh = &p->o_res.fh; |
763 | p->c_arg.stateid = &p->o_res.stateid; | 781 | p->c_arg.stateid = &p->o_res.stateid; |
@@ -1255,8 +1273,6 @@ static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | |||
1255 | struct nfs4_opendata *data = calldata; | 1273 | struct nfs4_opendata *data = calldata; |
1256 | 1274 | ||
1257 | data->rpc_status = task->tk_status; | 1275 | data->rpc_status = task->tk_status; |
1258 | if (RPC_ASSASSINATED(task)) | ||
1259 | return; | ||
1260 | if (data->rpc_status == 0) { | 1276 | if (data->rpc_status == 0) { |
1261 | memcpy(data->o_res.stateid.data, data->c_res.stateid.data, | 1277 | memcpy(data->o_res.stateid.data, data->c_res.stateid.data, |
1262 | sizeof(data->o_res.stateid.data)); | 1278 | sizeof(data->o_res.stateid.data)); |
@@ -1356,13 +1372,13 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) | |||
1356 | } | 1372 | } |
1357 | /* Update sequence id. */ | 1373 | /* Update sequence id. */ |
1358 | data->o_arg.id = sp->so_owner_id.id; | 1374 | data->o_arg.id = sp->so_owner_id.id; |
1359 | data->o_arg.clientid = sp->so_client->cl_clientid; | 1375 | data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; |
1360 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { | 1376 | if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { |
1361 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; | 1377 | task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; |
1362 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); | 1378 | nfs_copy_fh(&data->o_res.fh, data->o_arg.fh); |
1363 | } | 1379 | } |
1364 | data->timestamp = jiffies; | 1380 | data->timestamp = jiffies; |
1365 | if (nfs4_setup_sequence(data->o_arg.server->nfs_client, | 1381 | if (nfs4_setup_sequence(data->o_arg.server, |
1366 | &data->o_arg.seq_args, | 1382 | &data->o_arg.seq_args, |
1367 | &data->o_res.seq_res, 1, task)) | 1383 | &data->o_res.seq_res, 1, task)) |
1368 | return; | 1384 | return; |
@@ -1385,11 +1401,9 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata) | |||
1385 | 1401 | ||
1386 | data->rpc_status = task->tk_status; | 1402 | data->rpc_status = task->tk_status; |
1387 | 1403 | ||
1388 | nfs4_sequence_done(data->o_arg.server, &data->o_res.seq_res, | 1404 | if (!nfs4_sequence_done(task, &data->o_res.seq_res)) |
1389 | task->tk_status); | ||
1390 | |||
1391 | if (RPC_ASSASSINATED(task)) | ||
1392 | return; | 1405 | return; |
1406 | |||
1393 | if (task->tk_status == 0) { | 1407 | if (task->tk_status == 0) { |
1394 | switch (data->o_res.f_attr->mode & S_IFMT) { | 1408 | switch (data->o_res.f_attr->mode & S_IFMT) { |
1395 | case S_IFREG: | 1409 | case S_IFREG: |
@@ -1773,7 +1787,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
1773 | if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) { | 1787 | if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) { |
1774 | /* Use that stateid */ | 1788 | /* Use that stateid */ |
1775 | } else if (state != NULL) { | 1789 | } else if (state != NULL) { |
1776 | nfs4_copy_stateid(&arg.stateid, state, current->files); | 1790 | nfs4_copy_stateid(&arg.stateid, state, current->files, current->tgid); |
1777 | } else | 1791 | } else |
1778 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); | 1792 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); |
1779 | 1793 | ||
@@ -1838,8 +1852,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
1838 | struct nfs4_state *state = calldata->state; | 1852 | struct nfs4_state *state = calldata->state; |
1839 | struct nfs_server *server = NFS_SERVER(calldata->inode); | 1853 | struct nfs_server *server = NFS_SERVER(calldata->inode); |
1840 | 1854 | ||
1841 | nfs4_sequence_done(server, &calldata->res.seq_res, task->tk_status); | 1855 | if (!nfs4_sequence_done(task, &calldata->res.seq_res)) |
1842 | if (RPC_ASSASSINATED(task)) | ||
1843 | return; | 1856 | return; |
1844 | /* hmm. we are done with the inode, and in the process of freeing | 1857 | /* hmm. we are done with the inode, and in the process of freeing |
1845 | * the state_owner. we keep this around to process errors | 1858 | * the state_owner. we keep this around to process errors |
@@ -1903,7 +1916,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) | |||
1903 | 1916 | ||
1904 | nfs_fattr_init(calldata->res.fattr); | 1917 | nfs_fattr_init(calldata->res.fattr); |
1905 | calldata->timestamp = jiffies; | 1918 | calldata->timestamp = jiffies; |
1906 | if (nfs4_setup_sequence((NFS_SERVER(calldata->inode))->nfs_client, | 1919 | if (nfs4_setup_sequence(NFS_SERVER(calldata->inode), |
1907 | &calldata->arg.seq_args, &calldata->res.seq_res, | 1920 | &calldata->arg.seq_args, &calldata->res.seq_res, |
1908 | 1, task)) | 1921 | 1, task)) |
1909 | return; | 1922 | return; |
@@ -2648,7 +2661,8 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir) | |||
2648 | { | 2661 | { |
2649 | struct nfs_removeres *res = task->tk_msg.rpc_resp; | 2662 | struct nfs_removeres *res = task->tk_msg.rpc_resp; |
2650 | 2663 | ||
2651 | nfs4_sequence_done(res->server, &res->seq_res, task->tk_status); | 2664 | if (!nfs4_sequence_done(task, &res->seq_res)) |
2665 | return 0; | ||
2652 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) | 2666 | if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN) |
2653 | return 0; | 2667 | return 0; |
2654 | update_changeattr(dir, &res->cinfo); | 2668 | update_changeattr(dir, &res->cinfo); |
@@ -3093,7 +3107,8 @@ static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) | |||
3093 | 3107 | ||
3094 | dprintk("--> %s\n", __func__); | 3108 | dprintk("--> %s\n", __func__); |
3095 | 3109 | ||
3096 | nfs4_sequence_done(server, &data->res.seq_res, task->tk_status); | 3110 | if (!nfs4_sequence_done(task, &data->res.seq_res)) |
3111 | return -EAGAIN; | ||
3097 | 3112 | ||
3098 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { | 3113 | if (nfs4_async_handle_error(task, server, data->args.context->state) == -EAGAIN) { |
3099 | nfs_restart_rpc(task, server->nfs_client); | 3114 | nfs_restart_rpc(task, server->nfs_client); |
@@ -3116,8 +3131,8 @@ static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | |||
3116 | { | 3131 | { |
3117 | struct inode *inode = data->inode; | 3132 | struct inode *inode = data->inode; |
3118 | 3133 | ||
3119 | nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res, | 3134 | if (!nfs4_sequence_done(task, &data->res.seq_res)) |
3120 | task->tk_status); | 3135 | return -EAGAIN; |
3121 | 3136 | ||
3122 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { | 3137 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), data->args.context->state) == -EAGAIN) { |
3123 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); | 3138 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); |
@@ -3145,8 +3160,9 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_write_data *data) | |||
3145 | { | 3160 | { |
3146 | struct inode *inode = data->inode; | 3161 | struct inode *inode = data->inode; |
3147 | 3162 | ||
3148 | nfs4_sequence_done(NFS_SERVER(inode), &data->res.seq_res, | 3163 | if (!nfs4_sequence_done(task, &data->res.seq_res)) |
3149 | task->tk_status); | 3164 | return -EAGAIN; |
3165 | |||
3150 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { | 3166 | if (nfs4_async_handle_error(task, NFS_SERVER(inode), NULL) == -EAGAIN) { |
3151 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); | 3167 | nfs_restart_rpc(task, NFS_SERVER(inode)->nfs_client); |
3152 | return -EAGAIN; | 3168 | return -EAGAIN; |
@@ -3196,10 +3212,7 @@ static void nfs4_renew_done(struct rpc_task *task, void *calldata) | |||
3196 | nfs4_schedule_state_recovery(clp); | 3212 | nfs4_schedule_state_recovery(clp); |
3197 | return; | 3213 | return; |
3198 | } | 3214 | } |
3199 | spin_lock(&clp->cl_lock); | 3215 | do_renew_lease(clp, timestamp); |
3200 | if (time_before(clp->cl_last_renewal,timestamp)) | ||
3201 | clp->cl_last_renewal = timestamp; | ||
3202 | spin_unlock(&clp->cl_lock); | ||
3203 | } | 3216 | } |
3204 | 3217 | ||
3205 | static const struct rpc_call_ops nfs4_renew_ops = { | 3218 | static const struct rpc_call_ops nfs4_renew_ops = { |
@@ -3240,10 +3253,7 @@ int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) | |||
3240 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); | 3253 | status = rpc_call_sync(clp->cl_rpcclient, &msg, 0); |
3241 | if (status < 0) | 3254 | if (status < 0) |
3242 | return status; | 3255 | return status; |
3243 | spin_lock(&clp->cl_lock); | 3256 | do_renew_lease(clp, now); |
3244 | if (time_before(clp->cl_last_renewal,now)) | ||
3245 | clp->cl_last_renewal = now; | ||
3246 | spin_unlock(&clp->cl_lock); | ||
3247 | return 0; | 3257 | return 0; |
3248 | } | 3258 | } |
3249 | 3259 | ||
@@ -3464,9 +3474,11 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
3464 | } | 3474 | } |
3465 | 3475 | ||
3466 | static int | 3476 | static int |
3467 | _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs_client *clp, struct nfs4_state *state) | 3477 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) |
3468 | { | 3478 | { |
3469 | if (!clp || task->tk_status >= 0) | 3479 | struct nfs_client *clp = server->nfs_client; |
3480 | |||
3481 | if (task->tk_status >= 0) | ||
3470 | return 0; | 3482 | return 0; |
3471 | switch(task->tk_status) { | 3483 | switch(task->tk_status) { |
3472 | case -NFS4ERR_ADMIN_REVOKED: | 3484 | case -NFS4ERR_ADMIN_REVOKED: |
@@ -3498,8 +3510,7 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, | |||
3498 | return -EAGAIN; | 3510 | return -EAGAIN; |
3499 | #endif /* CONFIG_NFS_V4_1 */ | 3511 | #endif /* CONFIG_NFS_V4_1 */ |
3500 | case -NFS4ERR_DELAY: | 3512 | case -NFS4ERR_DELAY: |
3501 | if (server) | 3513 | nfs_inc_server_stats(server, NFSIOS_DELAY); |
3502 | nfs_inc_server_stats(server, NFSIOS_DELAY); | ||
3503 | case -NFS4ERR_GRACE: | 3514 | case -NFS4ERR_GRACE: |
3504 | case -EKEYEXPIRED: | 3515 | case -EKEYEXPIRED: |
3505 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 3516 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
@@ -3520,12 +3531,6 @@ do_state_recovery: | |||
3520 | return -EAGAIN; | 3531 | return -EAGAIN; |
3521 | } | 3532 | } |
3522 | 3533 | ||
3523 | static int | ||
3524 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) | ||
3525 | { | ||
3526 | return _nfs4_async_handle_error(task, server, server->nfs_client, state); | ||
3527 | } | ||
3528 | |||
3529 | int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, | 3534 | int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, |
3530 | unsigned short port, struct rpc_cred *cred, | 3535 | unsigned short port, struct rpc_cred *cred, |
3531 | struct nfs4_setclientid_res *res) | 3536 | struct nfs4_setclientid_res *res) |
@@ -3641,8 +3646,8 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
3641 | { | 3646 | { |
3642 | struct nfs4_delegreturndata *data = calldata; | 3647 | struct nfs4_delegreturndata *data = calldata; |
3643 | 3648 | ||
3644 | nfs4_sequence_done(data->res.server, &data->res.seq_res, | 3649 | if (!nfs4_sequence_done(task, &data->res.seq_res)) |
3645 | task->tk_status); | 3650 | return; |
3646 | 3651 | ||
3647 | switch (task->tk_status) { | 3652 | switch (task->tk_status) { |
3648 | case -NFS4ERR_STALE_STATEID: | 3653 | case -NFS4ERR_STALE_STATEID: |
@@ -3672,7 +3677,7 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data) | |||
3672 | 3677 | ||
3673 | d_data = (struct nfs4_delegreturndata *)data; | 3678 | d_data = (struct nfs4_delegreturndata *)data; |
3674 | 3679 | ||
3675 | if (nfs4_setup_sequence(d_data->res.server->nfs_client, | 3680 | if (nfs4_setup_sequence(d_data->res.server, |
3676 | &d_data->args.seq_args, | 3681 | &d_data->args.seq_args, |
3677 | &d_data->res.seq_res, 1, task)) | 3682 | &d_data->res.seq_res, 1, task)) |
3678 | return; | 3683 | return; |
@@ -3892,9 +3897,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) | |||
3892 | { | 3897 | { |
3893 | struct nfs4_unlockdata *calldata = data; | 3898 | struct nfs4_unlockdata *calldata = data; |
3894 | 3899 | ||
3895 | nfs4_sequence_done(calldata->server, &calldata->res.seq_res, | 3900 | if (!nfs4_sequence_done(task, &calldata->res.seq_res)) |
3896 | task->tk_status); | ||
3897 | if (RPC_ASSASSINATED(task)) | ||
3898 | return; | 3901 | return; |
3899 | switch (task->tk_status) { | 3902 | switch (task->tk_status) { |
3900 | case 0: | 3903 | case 0: |
@@ -3927,7 +3930,7 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) | |||
3927 | return; | 3930 | return; |
3928 | } | 3931 | } |
3929 | calldata->timestamp = jiffies; | 3932 | calldata->timestamp = jiffies; |
3930 | if (nfs4_setup_sequence(calldata->server->nfs_client, | 3933 | if (nfs4_setup_sequence(calldata->server, |
3931 | &calldata->arg.seq_args, | 3934 | &calldata->arg.seq_args, |
3932 | &calldata->res.seq_res, 1, task)) | 3935 | &calldata->res.seq_res, 1, task)) |
3933 | return; | 3936 | return; |
@@ -4082,7 +4085,8 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) | |||
4082 | } else | 4085 | } else |
4083 | data->arg.new_lock_owner = 0; | 4086 | data->arg.new_lock_owner = 0; |
4084 | data->timestamp = jiffies; | 4087 | data->timestamp = jiffies; |
4085 | if (nfs4_setup_sequence(data->server->nfs_client, &data->arg.seq_args, | 4088 | if (nfs4_setup_sequence(data->server, |
4089 | &data->arg.seq_args, | ||
4086 | &data->res.seq_res, 1, task)) | 4090 | &data->res.seq_res, 1, task)) |
4087 | return; | 4091 | return; |
4088 | rpc_call_start(task); | 4092 | rpc_call_start(task); |
@@ -4101,12 +4105,10 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata) | |||
4101 | 4105 | ||
4102 | dprintk("%s: begin!\n", __func__); | 4106 | dprintk("%s: begin!\n", __func__); |
4103 | 4107 | ||
4104 | nfs4_sequence_done(data->server, &data->res.seq_res, | 4108 | if (!nfs4_sequence_done(task, &data->res.seq_res)) |
4105 | task->tk_status); | 4109 | return; |
4106 | 4110 | ||
4107 | data->rpc_status = task->tk_status; | 4111 | data->rpc_status = task->tk_status; |
4108 | if (RPC_ASSASSINATED(task)) | ||
4109 | goto out; | ||
4110 | if (data->arg.new_lock_owner != 0) { | 4112 | if (data->arg.new_lock_owner != 0) { |
4111 | if (data->rpc_status == 0) | 4113 | if (data->rpc_status == 0) |
4112 | nfs_confirm_seqid(&data->lsp->ls_seqid, 0); | 4114 | nfs_confirm_seqid(&data->lsp->ls_seqid, 0); |
@@ -4424,6 +4426,34 @@ out: | |||
4424 | return err; | 4426 | return err; |
4425 | } | 4427 | } |
4426 | 4428 | ||
4429 | static void nfs4_release_lockowner_release(void *calldata) | ||
4430 | { | ||
4431 | kfree(calldata); | ||
4432 | } | ||
4433 | |||
4434 | const struct rpc_call_ops nfs4_release_lockowner_ops = { | ||
4435 | .rpc_release = nfs4_release_lockowner_release, | ||
4436 | }; | ||
4437 | |||
4438 | void nfs4_release_lockowner(const struct nfs4_lock_state *lsp) | ||
4439 | { | ||
4440 | struct nfs_server *server = lsp->ls_state->owner->so_server; | ||
4441 | struct nfs_release_lockowner_args *args; | ||
4442 | struct rpc_message msg = { | ||
4443 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RELEASE_LOCKOWNER], | ||
4444 | }; | ||
4445 | |||
4446 | if (server->nfs_client->cl_mvops->minor_version != 0) | ||
4447 | return; | ||
4448 | args = kmalloc(sizeof(*args), GFP_NOFS); | ||
4449 | if (!args) | ||
4450 | return; | ||
4451 | args->lock_owner.clientid = server->nfs_client->cl_clientid; | ||
4452 | args->lock_owner.id = lsp->ls_id.id; | ||
4453 | msg.rpc_argp = args; | ||
4454 | rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, args); | ||
4455 | } | ||
4456 | |||
4427 | #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" | 4457 | #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl" |
4428 | 4458 | ||
4429 | int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf, | 4459 | int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf, |
@@ -4611,7 +4641,8 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) | |||
4611 | (struct nfs4_get_lease_time_data *)calldata; | 4641 | (struct nfs4_get_lease_time_data *)calldata; |
4612 | 4642 | ||
4613 | dprintk("--> %s\n", __func__); | 4643 | dprintk("--> %s\n", __func__); |
4614 | nfs41_sequence_done(data->clp, &data->res->lr_seq_res, task->tk_status); | 4644 | if (!nfs41_sequence_done(task, &data->res->lr_seq_res)) |
4645 | return; | ||
4615 | switch (task->tk_status) { | 4646 | switch (task->tk_status) { |
4616 | case -NFS4ERR_DELAY: | 4647 | case -NFS4ERR_DELAY: |
4617 | case -NFS4ERR_GRACE: | 4648 | case -NFS4ERR_GRACE: |
@@ -4805,13 +4836,6 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
4805 | if (!session) | 4836 | if (!session) |
4806 | return NULL; | 4837 | return NULL; |
4807 | 4838 | ||
4808 | /* | ||
4809 | * The create session reply races with the server back | ||
4810 | * channel probe. Mark the client NFS_CS_SESSION_INITING | ||
4811 | * so that the client back channel can find the | ||
4812 | * nfs_client struct | ||
4813 | */ | ||
4814 | clp->cl_cons_state = NFS_CS_SESSION_INITING; | ||
4815 | init_completion(&session->complete); | 4839 | init_completion(&session->complete); |
4816 | 4840 | ||
4817 | tbl = &session->fc_slot_table; | 4841 | tbl = &session->fc_slot_table; |
@@ -4824,6 +4848,8 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
4824 | spin_lock_init(&tbl->slot_tbl_lock); | 4848 | spin_lock_init(&tbl->slot_tbl_lock); |
4825 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); | 4849 | rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table"); |
4826 | 4850 | ||
4851 | session->session_state = 1<<NFS4_SESSION_INITING; | ||
4852 | |||
4827 | session->clp = clp; | 4853 | session->clp = clp; |
4828 | return session; | 4854 | return session; |
4829 | } | 4855 | } |
@@ -5040,6 +5066,10 @@ int nfs4_init_session(struct nfs_server *server) | |||
5040 | if (!nfs4_has_session(clp)) | 5066 | if (!nfs4_has_session(clp)) |
5041 | return 0; | 5067 | return 0; |
5042 | 5068 | ||
5069 | session = clp->cl_session; | ||
5070 | if (!test_and_clear_bit(NFS4_SESSION_INITING, &session->session_state)) | ||
5071 | return 0; | ||
5072 | |||
5043 | rsize = server->rsize; | 5073 | rsize = server->rsize; |
5044 | if (rsize == 0) | 5074 | if (rsize == 0) |
5045 | rsize = NFS_MAX_FILE_IO_SIZE; | 5075 | rsize = NFS_MAX_FILE_IO_SIZE; |
@@ -5047,7 +5077,6 @@ int nfs4_init_session(struct nfs_server *server) | |||
5047 | if (wsize == 0) | 5077 | if (wsize == 0) |
5048 | wsize = NFS_MAX_FILE_IO_SIZE; | 5078 | wsize = NFS_MAX_FILE_IO_SIZE; |
5049 | 5079 | ||
5050 | session = clp->cl_session; | ||
5051 | session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead; | 5080 | session->fc_attrs.max_rqst_sz = wsize + nfs41_maxwrite_overhead; |
5052 | session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead; | 5081 | session->fc_attrs.max_resp_sz = rsize + nfs41_maxread_overhead; |
5053 | 5082 | ||
@@ -5060,69 +5089,70 @@ int nfs4_init_session(struct nfs_server *server) | |||
5060 | /* | 5089 | /* |
5061 | * Renew the cl_session lease. | 5090 | * Renew the cl_session lease. |
5062 | */ | 5091 | */ |
5063 | static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) | 5092 | struct nfs4_sequence_data { |
5064 | { | 5093 | struct nfs_client *clp; |
5065 | struct nfs4_sequence_args args; | 5094 | struct nfs4_sequence_args args; |
5066 | struct nfs4_sequence_res res; | 5095 | struct nfs4_sequence_res res; |
5067 | 5096 | }; | |
5068 | struct rpc_message msg = { | ||
5069 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE], | ||
5070 | .rpc_argp = &args, | ||
5071 | .rpc_resp = &res, | ||
5072 | .rpc_cred = cred, | ||
5073 | }; | ||
5074 | |||
5075 | args.sa_cache_this = 0; | ||
5076 | |||
5077 | return nfs4_call_sync_sequence(clp, clp->cl_rpcclient, &msg, &args, | ||
5078 | &res, args.sa_cache_this, 1); | ||
5079 | } | ||
5080 | 5097 | ||
5081 | static void nfs41_sequence_release(void *data) | 5098 | static void nfs41_sequence_release(void *data) |
5082 | { | 5099 | { |
5083 | struct nfs_client *clp = (struct nfs_client *)data; | 5100 | struct nfs4_sequence_data *calldata = data; |
5101 | struct nfs_client *clp = calldata->clp; | ||
5084 | 5102 | ||
5085 | if (atomic_read(&clp->cl_count) > 1) | 5103 | if (atomic_read(&clp->cl_count) > 1) |
5086 | nfs4_schedule_state_renewal(clp); | 5104 | nfs4_schedule_state_renewal(clp); |
5087 | nfs_put_client(clp); | 5105 | nfs_put_client(clp); |
5106 | kfree(calldata); | ||
5107 | } | ||
5108 | |||
5109 | static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client *clp) | ||
5110 | { | ||
5111 | switch(task->tk_status) { | ||
5112 | case -NFS4ERR_DELAY: | ||
5113 | case -EKEYEXPIRED: | ||
5114 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | ||
5115 | return -EAGAIN; | ||
5116 | default: | ||
5117 | nfs4_schedule_state_recovery(clp); | ||
5118 | } | ||
5119 | return 0; | ||
5088 | } | 5120 | } |
5089 | 5121 | ||
5090 | static void nfs41_sequence_call_done(struct rpc_task *task, void *data) | 5122 | static void nfs41_sequence_call_done(struct rpc_task *task, void *data) |
5091 | { | 5123 | { |
5092 | struct nfs_client *clp = (struct nfs_client *)data; | 5124 | struct nfs4_sequence_data *calldata = data; |
5125 | struct nfs_client *clp = calldata->clp; | ||
5093 | 5126 | ||
5094 | nfs41_sequence_done(clp, task->tk_msg.rpc_resp, task->tk_status); | 5127 | if (!nfs41_sequence_done(task, task->tk_msg.rpc_resp)) |
5128 | return; | ||
5095 | 5129 | ||
5096 | if (task->tk_status < 0) { | 5130 | if (task->tk_status < 0) { |
5097 | dprintk("%s ERROR %d\n", __func__, task->tk_status); | 5131 | dprintk("%s ERROR %d\n", __func__, task->tk_status); |
5098 | if (atomic_read(&clp->cl_count) == 1) | 5132 | if (atomic_read(&clp->cl_count) == 1) |
5099 | goto out; | 5133 | goto out; |
5100 | 5134 | ||
5101 | if (_nfs4_async_handle_error(task, NULL, clp, NULL) | 5135 | if (nfs41_sequence_handle_errors(task, clp) == -EAGAIN) { |
5102 | == -EAGAIN) { | 5136 | rpc_restart_call_prepare(task); |
5103 | nfs_restart_rpc(task, clp); | ||
5104 | return; | 5137 | return; |
5105 | } | 5138 | } |
5106 | } | 5139 | } |
5107 | dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred); | 5140 | dprintk("%s rpc_cred %p\n", __func__, task->tk_msg.rpc_cred); |
5108 | out: | 5141 | out: |
5109 | kfree(task->tk_msg.rpc_argp); | ||
5110 | kfree(task->tk_msg.rpc_resp); | ||
5111 | |||
5112 | dprintk("<-- %s\n", __func__); | 5142 | dprintk("<-- %s\n", __func__); |
5113 | } | 5143 | } |
5114 | 5144 | ||
5115 | static void nfs41_sequence_prepare(struct rpc_task *task, void *data) | 5145 | static void nfs41_sequence_prepare(struct rpc_task *task, void *data) |
5116 | { | 5146 | { |
5117 | struct nfs_client *clp; | 5147 | struct nfs4_sequence_data *calldata = data; |
5148 | struct nfs_client *clp = calldata->clp; | ||
5118 | struct nfs4_sequence_args *args; | 5149 | struct nfs4_sequence_args *args; |
5119 | struct nfs4_sequence_res *res; | 5150 | struct nfs4_sequence_res *res; |
5120 | 5151 | ||
5121 | clp = (struct nfs_client *)data; | ||
5122 | args = task->tk_msg.rpc_argp; | 5152 | args = task->tk_msg.rpc_argp; |
5123 | res = task->tk_msg.rpc_resp; | 5153 | res = task->tk_msg.rpc_resp; |
5124 | 5154 | ||
5125 | if (nfs4_setup_sequence(clp, args, res, 0, task)) | 5155 | if (nfs41_setup_sequence(clp->cl_session, args, res, 0, task)) |
5126 | return; | 5156 | return; |
5127 | rpc_call_start(task); | 5157 | rpc_call_start(task); |
5128 | } | 5158 | } |
@@ -5133,32 +5163,67 @@ static const struct rpc_call_ops nfs41_sequence_ops = { | |||
5133 | .rpc_release = nfs41_sequence_release, | 5163 | .rpc_release = nfs41_sequence_release, |
5134 | }; | 5164 | }; |
5135 | 5165 | ||
5136 | static int nfs41_proc_async_sequence(struct nfs_client *clp, | 5166 | static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) |
5137 | struct rpc_cred *cred) | ||
5138 | { | 5167 | { |
5139 | struct nfs4_sequence_args *args; | 5168 | struct nfs4_sequence_data *calldata; |
5140 | struct nfs4_sequence_res *res; | ||
5141 | struct rpc_message msg = { | 5169 | struct rpc_message msg = { |
5142 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE], | 5170 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE], |
5143 | .rpc_cred = cred, | 5171 | .rpc_cred = cred, |
5144 | }; | 5172 | }; |
5173 | struct rpc_task_setup task_setup_data = { | ||
5174 | .rpc_client = clp->cl_rpcclient, | ||
5175 | .rpc_message = &msg, | ||
5176 | .callback_ops = &nfs41_sequence_ops, | ||
5177 | .flags = RPC_TASK_ASYNC | RPC_TASK_SOFT, | ||
5178 | }; | ||
5145 | 5179 | ||
5146 | if (!atomic_inc_not_zero(&clp->cl_count)) | 5180 | if (!atomic_inc_not_zero(&clp->cl_count)) |
5147 | return -EIO; | 5181 | return ERR_PTR(-EIO); |
5148 | args = kzalloc(sizeof(*args), GFP_NOFS); | 5182 | calldata = kmalloc(sizeof(*calldata), GFP_NOFS); |
5149 | res = kzalloc(sizeof(*res), GFP_NOFS); | 5183 | if (calldata == NULL) { |
5150 | if (!args || !res) { | ||
5151 | kfree(args); | ||
5152 | kfree(res); | ||
5153 | nfs_put_client(clp); | 5184 | nfs_put_client(clp); |
5154 | return -ENOMEM; | 5185 | return ERR_PTR(-ENOMEM); |
5155 | } | 5186 | } |
5156 | res->sr_slotid = NFS4_MAX_SLOT_TABLE; | 5187 | calldata->res.sr_slotid = NFS4_MAX_SLOT_TABLE; |
5157 | msg.rpc_argp = args; | 5188 | msg.rpc_argp = &calldata->args; |
5158 | msg.rpc_resp = res; | 5189 | msg.rpc_resp = &calldata->res; |
5190 | calldata->clp = clp; | ||
5191 | task_setup_data.callback_data = calldata; | ||
5159 | 5192 | ||
5160 | return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, | 5193 | return rpc_run_task(&task_setup_data); |
5161 | &nfs41_sequence_ops, (void *)clp); | 5194 | } |
5195 | |||
5196 | static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred) | ||
5197 | { | ||
5198 | struct rpc_task *task; | ||
5199 | int ret = 0; | ||
5200 | |||
5201 | task = _nfs41_proc_sequence(clp, cred); | ||
5202 | if (IS_ERR(task)) | ||
5203 | ret = PTR_ERR(task); | ||
5204 | else | ||
5205 | rpc_put_task(task); | ||
5206 | dprintk("<-- %s status=%d\n", __func__, ret); | ||
5207 | return ret; | ||
5208 | } | ||
5209 | |||
5210 | static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) | ||
5211 | { | ||
5212 | struct rpc_task *task; | ||
5213 | int ret; | ||
5214 | |||
5215 | task = _nfs41_proc_sequence(clp, cred); | ||
5216 | if (IS_ERR(task)) { | ||
5217 | ret = PTR_ERR(task); | ||
5218 | goto out; | ||
5219 | } | ||
5220 | ret = rpc_wait_for_completion_task(task); | ||
5221 | if (!ret) | ||
5222 | ret = task->tk_status; | ||
5223 | rpc_put_task(task); | ||
5224 | out: | ||
5225 | dprintk("<-- %s status=%d\n", __func__, ret); | ||
5226 | return ret; | ||
5162 | } | 5227 | } |
5163 | 5228 | ||
5164 | struct nfs4_reclaim_complete_data { | 5229 | struct nfs4_reclaim_complete_data { |
@@ -5172,13 +5237,31 @@ static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data) | |||
5172 | struct nfs4_reclaim_complete_data *calldata = data; | 5237 | struct nfs4_reclaim_complete_data *calldata = data; |
5173 | 5238 | ||
5174 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); | 5239 | rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); |
5175 | if (nfs4_setup_sequence(calldata->clp, &calldata->arg.seq_args, | 5240 | if (nfs41_setup_sequence(calldata->clp->cl_session, |
5241 | &calldata->arg.seq_args, | ||
5176 | &calldata->res.seq_res, 0, task)) | 5242 | &calldata->res.seq_res, 0, task)) |
5177 | return; | 5243 | return; |
5178 | 5244 | ||
5179 | rpc_call_start(task); | 5245 | rpc_call_start(task); |
5180 | } | 5246 | } |
5181 | 5247 | ||
5248 | static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp) | ||
5249 | { | ||
5250 | switch(task->tk_status) { | ||
5251 | case 0: | ||
5252 | case -NFS4ERR_COMPLETE_ALREADY: | ||
5253 | case -NFS4ERR_WRONG_CRED: /* What to do here? */ | ||
5254 | break; | ||
5255 | case -NFS4ERR_DELAY: | ||
5256 | case -EKEYEXPIRED: | ||
5257 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | ||
5258 | return -EAGAIN; | ||
5259 | default: | ||
5260 | nfs4_schedule_state_recovery(clp); | ||
5261 | } | ||
5262 | return 0; | ||
5263 | } | ||
5264 | |||
5182 | static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data) | 5265 | static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data) |
5183 | { | 5266 | { |
5184 | struct nfs4_reclaim_complete_data *calldata = data; | 5267 | struct nfs4_reclaim_complete_data *calldata = data; |
@@ -5186,32 +5269,13 @@ static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data) | |||
5186 | struct nfs4_sequence_res *res = &calldata->res.seq_res; | 5269 | struct nfs4_sequence_res *res = &calldata->res.seq_res; |
5187 | 5270 | ||
5188 | dprintk("--> %s\n", __func__); | 5271 | dprintk("--> %s\n", __func__); |
5189 | nfs41_sequence_done(clp, res, task->tk_status); | 5272 | if (!nfs41_sequence_done(task, res)) |
5190 | switch (task->tk_status) { | 5273 | return; |
5191 | case 0: | ||
5192 | case -NFS4ERR_COMPLETE_ALREADY: | ||
5193 | break; | ||
5194 | case -NFS4ERR_BADSESSION: | ||
5195 | case -NFS4ERR_DEADSESSION: | ||
5196 | /* | ||
5197 | * Handle the session error, but do not retry the operation, as | ||
5198 | * we have no way of telling whether the clientid had to be | ||
5199 | * reset before we got our reply. If reset, a new wave of | ||
5200 | * reclaim operations will follow, containing their own reclaim | ||
5201 | * complete. We don't want our retry to get on the way of | ||
5202 | * recovery by incorrectly indicating to the server that we're | ||
5203 | * done reclaiming state since the process had to be restarted. | ||
5204 | */ | ||
5205 | _nfs4_async_handle_error(task, NULL, clp, NULL); | ||
5206 | break; | ||
5207 | default: | ||
5208 | if (_nfs4_async_handle_error( | ||
5209 | task, NULL, clp, NULL) == -EAGAIN) { | ||
5210 | rpc_restart_call_prepare(task); | ||
5211 | return; | ||
5212 | } | ||
5213 | } | ||
5214 | 5274 | ||
5275 | if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) { | ||
5276 | rpc_restart_call_prepare(task); | ||
5277 | return; | ||
5278 | } | ||
5215 | dprintk("<-- %s\n", __func__); | 5279 | dprintk("<-- %s\n", __func__); |
5216 | } | 5280 | } |
5217 | 5281 | ||
@@ -5325,28 +5389,30 @@ struct nfs4_state_maintenance_ops nfs41_state_renewal_ops = { | |||
5325 | }; | 5389 | }; |
5326 | #endif | 5390 | #endif |
5327 | 5391 | ||
5328 | /* | 5392 | static const struct nfs4_minor_version_ops nfs_v4_0_minor_ops = { |
5329 | * Per minor version reboot and network partition recovery ops | 5393 | .minor_version = 0, |
5330 | */ | 5394 | .call_sync = _nfs4_call_sync, |
5331 | 5395 | .validate_stateid = nfs4_validate_delegation_stateid, | |
5332 | struct nfs4_state_recovery_ops *nfs4_reboot_recovery_ops[] = { | 5396 | .reboot_recovery_ops = &nfs40_reboot_recovery_ops, |
5333 | &nfs40_reboot_recovery_ops, | 5397 | .nograce_recovery_ops = &nfs40_nograce_recovery_ops, |
5334 | #if defined(CONFIG_NFS_V4_1) | 5398 | .state_renewal_ops = &nfs40_state_renewal_ops, |
5335 | &nfs41_reboot_recovery_ops, | ||
5336 | #endif | ||
5337 | }; | 5399 | }; |
5338 | 5400 | ||
5339 | struct nfs4_state_recovery_ops *nfs4_nograce_recovery_ops[] = { | ||
5340 | &nfs40_nograce_recovery_ops, | ||
5341 | #if defined(CONFIG_NFS_V4_1) | 5401 | #if defined(CONFIG_NFS_V4_1) |
5342 | &nfs41_nograce_recovery_ops, | 5402 | static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = { |
5343 | #endif | 5403 | .minor_version = 1, |
5404 | .call_sync = _nfs4_call_sync_session, | ||
5405 | .validate_stateid = nfs41_validate_delegation_stateid, | ||
5406 | .reboot_recovery_ops = &nfs41_reboot_recovery_ops, | ||
5407 | .nograce_recovery_ops = &nfs41_nograce_recovery_ops, | ||
5408 | .state_renewal_ops = &nfs41_state_renewal_ops, | ||
5344 | }; | 5409 | }; |
5410 | #endif | ||
5345 | 5411 | ||
5346 | struct nfs4_state_maintenance_ops *nfs4_state_renewal_ops[] = { | 5412 | const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { |
5347 | &nfs40_state_renewal_ops, | 5413 | [0] = &nfs_v4_0_minor_ops, |
5348 | #if defined(CONFIG_NFS_V4_1) | 5414 | #if defined(CONFIG_NFS_V4_1) |
5349 | &nfs41_state_renewal_ops, | 5415 | [1] = &nfs_v4_1_minor_ops, |
5350 | #endif | 5416 | #endif |
5351 | }; | 5417 | }; |
5352 | 5418 | ||
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c index d87f10327b72..72b6c580af13 100644 --- a/fs/nfs/nfs4renewd.c +++ b/fs/nfs/nfs4renewd.c | |||
@@ -54,14 +54,14 @@ | |||
54 | void | 54 | void |
55 | nfs4_renew_state(struct work_struct *work) | 55 | nfs4_renew_state(struct work_struct *work) |
56 | { | 56 | { |
57 | struct nfs4_state_maintenance_ops *ops; | 57 | const struct nfs4_state_maintenance_ops *ops; |
58 | struct nfs_client *clp = | 58 | struct nfs_client *clp = |
59 | container_of(work, struct nfs_client, cl_renewd.work); | 59 | container_of(work, struct nfs_client, cl_renewd.work); |
60 | struct rpc_cred *cred; | 60 | struct rpc_cred *cred; |
61 | long lease; | 61 | long lease; |
62 | unsigned long last, now; | 62 | unsigned long last, now; |
63 | 63 | ||
64 | ops = nfs4_state_renewal_ops[clp->cl_minorversion]; | 64 | ops = clp->cl_mvops->state_renewal_ops; |
65 | dprintk("%s: start\n", __func__); | 65 | dprintk("%s: start\n", __func__); |
66 | /* Are there any active superblocks? */ | 66 | /* Are there any active superblocks? */ |
67 | if (list_empty(&clp->cl_superblocks)) | 67 | if (list_empty(&clp->cl_superblocks)) |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 34acf5926fdc..3e2f19b04c06 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -145,7 +145,9 @@ static void nfs4_end_drain_session(struct nfs_client *clp) | |||
145 | struct nfs4_session *ses = clp->cl_session; | 145 | struct nfs4_session *ses = clp->cl_session; |
146 | int max_slots; | 146 | int max_slots; |
147 | 147 | ||
148 | if (test_and_clear_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state)) { | 148 | if (ses == NULL) |
149 | return; | ||
150 | if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) { | ||
149 | spin_lock(&ses->fc_slot_table.slot_tbl_lock); | 151 | spin_lock(&ses->fc_slot_table.slot_tbl_lock); |
150 | max_slots = ses->fc_slot_table.max_slots; | 152 | max_slots = ses->fc_slot_table.max_slots; |
151 | while (max_slots--) { | 153 | while (max_slots--) { |
@@ -167,7 +169,7 @@ static int nfs4_begin_drain_session(struct nfs_client *clp) | |||
167 | struct nfs4_slot_table *tbl = &ses->fc_slot_table; | 169 | struct nfs4_slot_table *tbl = &ses->fc_slot_table; |
168 | 170 | ||
169 | spin_lock(&tbl->slot_tbl_lock); | 171 | spin_lock(&tbl->slot_tbl_lock); |
170 | set_bit(NFS4CLNT_SESSION_DRAINING, &clp->cl_state); | 172 | set_bit(NFS4_SESSION_DRAINING, &ses->session_state); |
171 | if (tbl->highest_used_slotid != -1) { | 173 | if (tbl->highest_used_slotid != -1) { |
172 | INIT_COMPLETION(ses->complete); | 174 | INIT_COMPLETION(ses->complete); |
173 | spin_unlock(&tbl->slot_tbl_lock); | 175 | spin_unlock(&tbl->slot_tbl_lock); |
@@ -371,7 +373,6 @@ nfs4_alloc_state_owner(void) | |||
371 | return NULL; | 373 | return NULL; |
372 | spin_lock_init(&sp->so_lock); | 374 | spin_lock_init(&sp->so_lock); |
373 | INIT_LIST_HEAD(&sp->so_states); | 375 | INIT_LIST_HEAD(&sp->so_states); |
374 | INIT_LIST_HEAD(&sp->so_delegations); | ||
375 | rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue"); | 376 | rpc_init_wait_queue(&sp->so_sequence.wait, "Seqid_waitqueue"); |
376 | sp->so_seqid.sequence = &sp->so_sequence; | 377 | sp->so_seqid.sequence = &sp->so_sequence; |
377 | spin_lock_init(&sp->so_sequence.lock); | 378 | spin_lock_init(&sp->so_sequence.lock); |
@@ -384,7 +385,7 @@ static void | |||
384 | nfs4_drop_state_owner(struct nfs4_state_owner *sp) | 385 | nfs4_drop_state_owner(struct nfs4_state_owner *sp) |
385 | { | 386 | { |
386 | if (!RB_EMPTY_NODE(&sp->so_client_node)) { | 387 | if (!RB_EMPTY_NODE(&sp->so_client_node)) { |
387 | struct nfs_client *clp = sp->so_client; | 388 | struct nfs_client *clp = sp->so_server->nfs_client; |
388 | 389 | ||
389 | spin_lock(&clp->cl_lock); | 390 | spin_lock(&clp->cl_lock); |
390 | rb_erase(&sp->so_client_node, &clp->cl_state_owners); | 391 | rb_erase(&sp->so_client_node, &clp->cl_state_owners); |
@@ -406,7 +407,6 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct | |||
406 | new = nfs4_alloc_state_owner(); | 407 | new = nfs4_alloc_state_owner(); |
407 | if (new == NULL) | 408 | if (new == NULL) |
408 | return NULL; | 409 | return NULL; |
409 | new->so_client = clp; | ||
410 | new->so_server = server; | 410 | new->so_server = server; |
411 | new->so_cred = cred; | 411 | new->so_cred = cred; |
412 | spin_lock(&clp->cl_lock); | 412 | spin_lock(&clp->cl_lock); |
@@ -423,7 +423,7 @@ struct nfs4_state_owner *nfs4_get_state_owner(struct nfs_server *server, struct | |||
423 | 423 | ||
424 | void nfs4_put_state_owner(struct nfs4_state_owner *sp) | 424 | void nfs4_put_state_owner(struct nfs4_state_owner *sp) |
425 | { | 425 | { |
426 | struct nfs_client *clp = sp->so_client; | 426 | struct nfs_client *clp = sp->so_server->nfs_client; |
427 | struct rpc_cred *cred = sp->so_cred; | 427 | struct rpc_cred *cred = sp->so_cred; |
428 | 428 | ||
429 | if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) | 429 | if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) |
@@ -602,12 +602,21 @@ void nfs4_close_sync(struct path *path, struct nfs4_state *state, fmode_t fmode) | |||
602 | * that is compatible with current->files | 602 | * that is compatible with current->files |
603 | */ | 603 | */ |
604 | static struct nfs4_lock_state * | 604 | static struct nfs4_lock_state * |
605 | __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | 605 | __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type) |
606 | { | 606 | { |
607 | struct nfs4_lock_state *pos; | 607 | struct nfs4_lock_state *pos; |
608 | list_for_each_entry(pos, &state->lock_states, ls_locks) { | 608 | list_for_each_entry(pos, &state->lock_states, ls_locks) { |
609 | if (pos->ls_owner != fl_owner) | 609 | if (type != NFS4_ANY_LOCK_TYPE && pos->ls_owner.lo_type != type) |
610 | continue; | 610 | continue; |
611 | switch (pos->ls_owner.lo_type) { | ||
612 | case NFS4_POSIX_LOCK_TYPE: | ||
613 | if (pos->ls_owner.lo_u.posix_owner != fl_owner) | ||
614 | continue; | ||
615 | break; | ||
616 | case NFS4_FLOCK_LOCK_TYPE: | ||
617 | if (pos->ls_owner.lo_u.flock_owner != fl_pid) | ||
618 | continue; | ||
619 | } | ||
611 | atomic_inc(&pos->ls_count); | 620 | atomic_inc(&pos->ls_count); |
612 | return pos; | 621 | return pos; |
613 | } | 622 | } |
@@ -619,10 +628,10 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | |||
619 | * exists, return an uninitialized one. | 628 | * exists, return an uninitialized one. |
620 | * | 629 | * |
621 | */ | 630 | */ |
622 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | 631 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type) |
623 | { | 632 | { |
624 | struct nfs4_lock_state *lsp; | 633 | struct nfs4_lock_state *lsp; |
625 | struct nfs_client *clp = state->owner->so_client; | 634 | struct nfs_client *clp = state->owner->so_server->nfs_client; |
626 | 635 | ||
627 | lsp = kzalloc(sizeof(*lsp), GFP_NOFS); | 636 | lsp = kzalloc(sizeof(*lsp), GFP_NOFS); |
628 | if (lsp == NULL) | 637 | if (lsp == NULL) |
@@ -633,7 +642,18 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
633 | lsp->ls_seqid.sequence = &lsp->ls_sequence; | 642 | lsp->ls_seqid.sequence = &lsp->ls_sequence; |
634 | atomic_set(&lsp->ls_count, 1); | 643 | atomic_set(&lsp->ls_count, 1); |
635 | lsp->ls_state = state; | 644 | lsp->ls_state = state; |
636 | lsp->ls_owner = fl_owner; | 645 | lsp->ls_owner.lo_type = type; |
646 | switch (lsp->ls_owner.lo_type) { | ||
647 | case NFS4_FLOCK_LOCK_TYPE: | ||
648 | lsp->ls_owner.lo_u.flock_owner = fl_pid; | ||
649 | break; | ||
650 | case NFS4_POSIX_LOCK_TYPE: | ||
651 | lsp->ls_owner.lo_u.posix_owner = fl_owner; | ||
652 | break; | ||
653 | default: | ||
654 | kfree(lsp); | ||
655 | return NULL; | ||
656 | } | ||
637 | spin_lock(&clp->cl_lock); | 657 | spin_lock(&clp->cl_lock); |
638 | nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64); | 658 | nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64); |
639 | spin_unlock(&clp->cl_lock); | 659 | spin_unlock(&clp->cl_lock); |
@@ -643,7 +663,7 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
643 | 663 | ||
644 | static void nfs4_free_lock_state(struct nfs4_lock_state *lsp) | 664 | static void nfs4_free_lock_state(struct nfs4_lock_state *lsp) |
645 | { | 665 | { |
646 | struct nfs_client *clp = lsp->ls_state->owner->so_client; | 666 | struct nfs_client *clp = lsp->ls_state->owner->so_server->nfs_client; |
647 | 667 | ||
648 | spin_lock(&clp->cl_lock); | 668 | spin_lock(&clp->cl_lock); |
649 | nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id); | 669 | nfs_free_unique_id(&clp->cl_lockowner_id, &lsp->ls_id); |
@@ -657,13 +677,13 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp) | |||
657 | * exists, return an uninitialized one. | 677 | * exists, return an uninitialized one. |
658 | * | 678 | * |
659 | */ | 679 | */ |
660 | static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) | 680 | static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner, pid_t pid, unsigned int type) |
661 | { | 681 | { |
662 | struct nfs4_lock_state *lsp, *new = NULL; | 682 | struct nfs4_lock_state *lsp, *new = NULL; |
663 | 683 | ||
664 | for(;;) { | 684 | for(;;) { |
665 | spin_lock(&state->state_lock); | 685 | spin_lock(&state->state_lock); |
666 | lsp = __nfs4_find_lock_state(state, owner); | 686 | lsp = __nfs4_find_lock_state(state, owner, pid, type); |
667 | if (lsp != NULL) | 687 | if (lsp != NULL) |
668 | break; | 688 | break; |
669 | if (new != NULL) { | 689 | if (new != NULL) { |
@@ -674,7 +694,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_ | |||
674 | break; | 694 | break; |
675 | } | 695 | } |
676 | spin_unlock(&state->state_lock); | 696 | spin_unlock(&state->state_lock); |
677 | new = nfs4_alloc_lock_state(state, owner); | 697 | new = nfs4_alloc_lock_state(state, owner, pid, type); |
678 | if (new == NULL) | 698 | if (new == NULL) |
679 | return NULL; | 699 | return NULL; |
680 | } | 700 | } |
@@ -701,6 +721,8 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp) | |||
701 | if (list_empty(&state->lock_states)) | 721 | if (list_empty(&state->lock_states)) |
702 | clear_bit(LK_STATE_IN_USE, &state->flags); | 722 | clear_bit(LK_STATE_IN_USE, &state->flags); |
703 | spin_unlock(&state->state_lock); | 723 | spin_unlock(&state->state_lock); |
724 | if (lsp->ls_flags & NFS_LOCK_INITIALIZED) | ||
725 | nfs4_release_lockowner(lsp); | ||
704 | nfs4_free_lock_state(lsp); | 726 | nfs4_free_lock_state(lsp); |
705 | } | 727 | } |
706 | 728 | ||
@@ -728,7 +750,12 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl) | |||
728 | 750 | ||
729 | if (fl->fl_ops != NULL) | 751 | if (fl->fl_ops != NULL) |
730 | return 0; | 752 | return 0; |
731 | lsp = nfs4_get_lock_state(state, fl->fl_owner); | 753 | if (fl->fl_flags & FL_POSIX) |
754 | lsp = nfs4_get_lock_state(state, fl->fl_owner, 0, NFS4_POSIX_LOCK_TYPE); | ||
755 | else if (fl->fl_flags & FL_FLOCK) | ||
756 | lsp = nfs4_get_lock_state(state, 0, fl->fl_pid, NFS4_FLOCK_LOCK_TYPE); | ||
757 | else | ||
758 | return -EINVAL; | ||
732 | if (lsp == NULL) | 759 | if (lsp == NULL) |
733 | return -ENOMEM; | 760 | return -ENOMEM; |
734 | fl->fl_u.nfs4_fl.owner = lsp; | 761 | fl->fl_u.nfs4_fl.owner = lsp; |
@@ -740,7 +767,7 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl) | |||
740 | * Byte-range lock aware utility to initialize the stateid of read/write | 767 | * Byte-range lock aware utility to initialize the stateid of read/write |
741 | * requests. | 768 | * requests. |
742 | */ | 769 | */ |
743 | void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner) | 770 | void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid) |
744 | { | 771 | { |
745 | struct nfs4_lock_state *lsp; | 772 | struct nfs4_lock_state *lsp; |
746 | int seq; | 773 | int seq; |
@@ -753,7 +780,7 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f | |||
753 | return; | 780 | return; |
754 | 781 | ||
755 | spin_lock(&state->state_lock); | 782 | spin_lock(&state->state_lock); |
756 | lsp = __nfs4_find_lock_state(state, fl_owner); | 783 | lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE); |
757 | if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) | 784 | if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) |
758 | memcpy(dst, &lsp->ls_stateid, sizeof(*dst)); | 785 | memcpy(dst, &lsp->ls_stateid, sizeof(*dst)); |
759 | spin_unlock(&state->state_lock); | 786 | spin_unlock(&state->state_lock); |
@@ -1041,11 +1068,11 @@ restart: | |||
1041 | case -NFS4ERR_BAD_STATEID: | 1068 | case -NFS4ERR_BAD_STATEID: |
1042 | case -NFS4ERR_RECLAIM_BAD: | 1069 | case -NFS4ERR_RECLAIM_BAD: |
1043 | case -NFS4ERR_RECLAIM_CONFLICT: | 1070 | case -NFS4ERR_RECLAIM_CONFLICT: |
1044 | nfs4_state_mark_reclaim_nograce(sp->so_client, state); | 1071 | nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state); |
1045 | break; | 1072 | break; |
1046 | case -NFS4ERR_EXPIRED: | 1073 | case -NFS4ERR_EXPIRED: |
1047 | case -NFS4ERR_NO_GRACE: | 1074 | case -NFS4ERR_NO_GRACE: |
1048 | nfs4_state_mark_reclaim_nograce(sp->so_client, state); | 1075 | nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state); |
1049 | case -NFS4ERR_STALE_CLIENTID: | 1076 | case -NFS4ERR_STALE_CLIENTID: |
1050 | case -NFS4ERR_BADSESSION: | 1077 | case -NFS4ERR_BADSESSION: |
1051 | case -NFS4ERR_BADSLOT: | 1078 | case -NFS4ERR_BADSLOT: |
@@ -1120,8 +1147,7 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp) | |||
1120 | if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) | 1147 | if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) |
1121 | return; | 1148 | return; |
1122 | 1149 | ||
1123 | nfs4_reclaim_complete(clp, | 1150 | nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops); |
1124 | nfs4_reboot_recovery_ops[clp->cl_minorversion]); | ||
1125 | 1151 | ||
1126 | for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { | 1152 | for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) { |
1127 | sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); | 1153 | sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); |
@@ -1211,8 +1237,8 @@ restart: | |||
1211 | static int nfs4_check_lease(struct nfs_client *clp) | 1237 | static int nfs4_check_lease(struct nfs_client *clp) |
1212 | { | 1238 | { |
1213 | struct rpc_cred *cred; | 1239 | struct rpc_cred *cred; |
1214 | struct nfs4_state_maintenance_ops *ops = | 1240 | const struct nfs4_state_maintenance_ops *ops = |
1215 | nfs4_state_renewal_ops[clp->cl_minorversion]; | 1241 | clp->cl_mvops->state_renewal_ops; |
1216 | int status = -NFS4ERR_EXPIRED; | 1242 | int status = -NFS4ERR_EXPIRED; |
1217 | 1243 | ||
1218 | /* Is the client already known to have an expired lease? */ | 1244 | /* Is the client already known to have an expired lease? */ |
@@ -1235,8 +1261,8 @@ out: | |||
1235 | static int nfs4_reclaim_lease(struct nfs_client *clp) | 1261 | static int nfs4_reclaim_lease(struct nfs_client *clp) |
1236 | { | 1262 | { |
1237 | struct rpc_cred *cred; | 1263 | struct rpc_cred *cred; |
1238 | struct nfs4_state_recovery_ops *ops = | 1264 | const struct nfs4_state_recovery_ops *ops = |
1239 | nfs4_reboot_recovery_ops[clp->cl_minorversion]; | 1265 | clp->cl_mvops->reboot_recovery_ops; |
1240 | int status = -ENOENT; | 1266 | int status = -ENOENT; |
1241 | 1267 | ||
1242 | cred = ops->get_clid_cred(clp); | 1268 | cred = ops->get_clid_cred(clp); |
@@ -1444,7 +1470,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1444 | /* First recover reboot state... */ | 1470 | /* First recover reboot state... */ |
1445 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { | 1471 | if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { |
1446 | status = nfs4_do_reclaim(clp, | 1472 | status = nfs4_do_reclaim(clp, |
1447 | nfs4_reboot_recovery_ops[clp->cl_minorversion]); | 1473 | clp->cl_mvops->reboot_recovery_ops); |
1448 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || | 1474 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
1449 | test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) | 1475 | test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) |
1450 | continue; | 1476 | continue; |
@@ -1458,7 +1484,7 @@ static void nfs4_state_manager(struct nfs_client *clp) | |||
1458 | /* Now recover expired state... */ | 1484 | /* Now recover expired state... */ |
1459 | if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { | 1485 | if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { |
1460 | status = nfs4_do_reclaim(clp, | 1486 | status = nfs4_do_reclaim(clp, |
1461 | nfs4_nograce_recovery_ops[clp->cl_minorversion]); | 1487 | clp->cl_mvops->nograce_recovery_ops); |
1462 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || | 1488 | if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) || |
1463 | test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) || | 1489 | test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) || |
1464 | test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) | 1490 | test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 65c8dae4b267..08ef91291132 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -202,14 +202,17 @@ static int nfs4_stat_to_errno(int); | |||
202 | #define encode_link_maxsz (op_encode_hdr_maxsz + \ | 202 | #define encode_link_maxsz (op_encode_hdr_maxsz + \ |
203 | nfs4_name_maxsz) | 203 | nfs4_name_maxsz) |
204 | #define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz) | 204 | #define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz) |
205 | #define encode_lockowner_maxsz (7) | ||
205 | #define encode_lock_maxsz (op_encode_hdr_maxsz + \ | 206 | #define encode_lock_maxsz (op_encode_hdr_maxsz + \ |
206 | 7 + \ | 207 | 7 + \ |
207 | 1 + encode_stateid_maxsz + 8) | 208 | 1 + encode_stateid_maxsz + 1 + \ |
209 | encode_lockowner_maxsz) | ||
208 | #define decode_lock_denied_maxsz \ | 210 | #define decode_lock_denied_maxsz \ |
209 | (8 + decode_lockowner_maxsz) | 211 | (8 + decode_lockowner_maxsz) |
210 | #define decode_lock_maxsz (op_decode_hdr_maxsz + \ | 212 | #define decode_lock_maxsz (op_decode_hdr_maxsz + \ |
211 | decode_lock_denied_maxsz) | 213 | decode_lock_denied_maxsz) |
212 | #define encode_lockt_maxsz (op_encode_hdr_maxsz + 12) | 214 | #define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \ |
215 | encode_lockowner_maxsz) | ||
213 | #define decode_lockt_maxsz (op_decode_hdr_maxsz + \ | 216 | #define decode_lockt_maxsz (op_decode_hdr_maxsz + \ |
214 | decode_lock_denied_maxsz) | 217 | decode_lock_denied_maxsz) |
215 | #define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \ | 218 | #define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \ |
@@ -217,6 +220,11 @@ static int nfs4_stat_to_errno(int); | |||
217 | 4) | 220 | 4) |
218 | #define decode_locku_maxsz (op_decode_hdr_maxsz + \ | 221 | #define decode_locku_maxsz (op_decode_hdr_maxsz + \ |
219 | decode_stateid_maxsz) | 222 | decode_stateid_maxsz) |
223 | #define encode_release_lockowner_maxsz \ | ||
224 | (op_encode_hdr_maxsz + \ | ||
225 | encode_lockowner_maxsz) | ||
226 | #define decode_release_lockowner_maxsz \ | ||
227 | (op_decode_hdr_maxsz) | ||
220 | #define encode_access_maxsz (op_encode_hdr_maxsz + 1) | 228 | #define encode_access_maxsz (op_encode_hdr_maxsz + 1) |
221 | #define decode_access_maxsz (op_decode_hdr_maxsz + 2) | 229 | #define decode_access_maxsz (op_decode_hdr_maxsz + 2) |
222 | #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ | 230 | #define encode_symlink_maxsz (op_encode_hdr_maxsz + \ |
@@ -471,6 +479,12 @@ static int nfs4_stat_to_errno(int); | |||
471 | decode_sequence_maxsz + \ | 479 | decode_sequence_maxsz + \ |
472 | decode_putfh_maxsz + \ | 480 | decode_putfh_maxsz + \ |
473 | decode_locku_maxsz) | 481 | decode_locku_maxsz) |
482 | #define NFS4_enc_release_lockowner_sz \ | ||
483 | (compound_encode_hdr_maxsz + \ | ||
484 | encode_lockowner_maxsz) | ||
485 | #define NFS4_dec_release_lockowner_sz \ | ||
486 | (compound_decode_hdr_maxsz + \ | ||
487 | decode_lockowner_maxsz) | ||
474 | #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ | 488 | #define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \ |
475 | encode_sequence_maxsz + \ | 489 | encode_sequence_maxsz + \ |
476 | encode_putfh_maxsz + \ | 490 | encode_putfh_maxsz + \ |
@@ -744,7 +758,7 @@ static void encode_compound_hdr(struct xdr_stream *xdr, | |||
744 | struct compound_hdr *hdr) | 758 | struct compound_hdr *hdr) |
745 | { | 759 | { |
746 | __be32 *p; | 760 | __be32 *p; |
747 | struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; | 761 | struct rpc_auth *auth = req->rq_cred->cr_auth; |
748 | 762 | ||
749 | /* initialize running count of expected bytes in reply. | 763 | /* initialize running count of expected bytes in reply. |
750 | * NOTE: the replied tag SHOULD be the same is the one sent, | 764 | * NOTE: the replied tag SHOULD be the same is the one sent, |
@@ -1042,6 +1056,17 @@ static inline uint64_t nfs4_lock_length(struct file_lock *fl) | |||
1042 | return fl->fl_end - fl->fl_start + 1; | 1056 | return fl->fl_end - fl->fl_start + 1; |
1043 | } | 1057 | } |
1044 | 1058 | ||
1059 | static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner) | ||
1060 | { | ||
1061 | __be32 *p; | ||
1062 | |||
1063 | p = reserve_space(xdr, 28); | ||
1064 | p = xdr_encode_hyper(p, lowner->clientid); | ||
1065 | *p++ = cpu_to_be32(16); | ||
1066 | p = xdr_encode_opaque_fixed(p, "lock id:", 8); | ||
1067 | xdr_encode_hyper(p, lowner->id); | ||
1068 | } | ||
1069 | |||
1045 | /* | 1070 | /* |
1046 | * opcode,type,reclaim,offset,length,new_lock_owner = 32 | 1071 | * opcode,type,reclaim,offset,length,new_lock_owner = 32 |
1047 | * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 | 1072 | * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40 |
@@ -1058,14 +1083,11 @@ static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args | |||
1058 | p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); | 1083 | p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); |
1059 | *p = cpu_to_be32(args->new_lock_owner); | 1084 | *p = cpu_to_be32(args->new_lock_owner); |
1060 | if (args->new_lock_owner){ | 1085 | if (args->new_lock_owner){ |
1061 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+32); | 1086 | p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4); |
1062 | *p++ = cpu_to_be32(args->open_seqid->sequence->counter); | 1087 | *p++ = cpu_to_be32(args->open_seqid->sequence->counter); |
1063 | p = xdr_encode_opaque_fixed(p, args->open_stateid->data, NFS4_STATEID_SIZE); | 1088 | p = xdr_encode_opaque_fixed(p, args->open_stateid->data, NFS4_STATEID_SIZE); |
1064 | *p++ = cpu_to_be32(args->lock_seqid->sequence->counter); | 1089 | *p++ = cpu_to_be32(args->lock_seqid->sequence->counter); |
1065 | p = xdr_encode_hyper(p, args->lock_owner.clientid); | 1090 | encode_lockowner(xdr, &args->lock_owner); |
1066 | *p++ = cpu_to_be32(16); | ||
1067 | p = xdr_encode_opaque_fixed(p, "lock id:", 8); | ||
1068 | xdr_encode_hyper(p, args->lock_owner.id); | ||
1069 | } | 1091 | } |
1070 | else { | 1092 | else { |
1071 | p = reserve_space(xdr, NFS4_STATEID_SIZE+4); | 1093 | p = reserve_space(xdr, NFS4_STATEID_SIZE+4); |
@@ -1080,15 +1102,12 @@ static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *ar | |||
1080 | { | 1102 | { |
1081 | __be32 *p; | 1103 | __be32 *p; |
1082 | 1104 | ||
1083 | p = reserve_space(xdr, 52); | 1105 | p = reserve_space(xdr, 24); |
1084 | *p++ = cpu_to_be32(OP_LOCKT); | 1106 | *p++ = cpu_to_be32(OP_LOCKT); |
1085 | *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); | 1107 | *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0)); |
1086 | p = xdr_encode_hyper(p, args->fl->fl_start); | 1108 | p = xdr_encode_hyper(p, args->fl->fl_start); |
1087 | p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); | 1109 | p = xdr_encode_hyper(p, nfs4_lock_length(args->fl)); |
1088 | p = xdr_encode_hyper(p, args->lock_owner.clientid); | 1110 | encode_lockowner(xdr, &args->lock_owner); |
1089 | *p++ = cpu_to_be32(16); | ||
1090 | p = xdr_encode_opaque_fixed(p, "lock id:", 8); | ||
1091 | xdr_encode_hyper(p, args->lock_owner.id); | ||
1092 | hdr->nops++; | 1111 | hdr->nops++; |
1093 | hdr->replen += decode_lockt_maxsz; | 1112 | hdr->replen += decode_lockt_maxsz; |
1094 | } | 1113 | } |
@@ -1108,6 +1127,17 @@ static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *ar | |||
1108 | hdr->replen += decode_locku_maxsz; | 1127 | hdr->replen += decode_locku_maxsz; |
1109 | } | 1128 | } |
1110 | 1129 | ||
1130 | static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr) | ||
1131 | { | ||
1132 | __be32 *p; | ||
1133 | |||
1134 | p = reserve_space(xdr, 4); | ||
1135 | *p = cpu_to_be32(OP_RELEASE_LOCKOWNER); | ||
1136 | encode_lockowner(xdr, lowner); | ||
1137 | hdr->nops++; | ||
1138 | hdr->replen += decode_release_lockowner_maxsz; | ||
1139 | } | ||
1140 | |||
1111 | static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) | 1141 | static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) |
1112 | { | 1142 | { |
1113 | int len = name->len; | 1143 | int len = name->len; |
@@ -1172,7 +1202,7 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op | |||
1172 | break; | 1202 | break; |
1173 | default: | 1203 | default: |
1174 | clp = arg->server->nfs_client; | 1204 | clp = arg->server->nfs_client; |
1175 | if (clp->cl_minorversion > 0) { | 1205 | if (clp->cl_mvops->minor_version > 0) { |
1176 | if (nfs4_has_persistent_session(clp)) { | 1206 | if (nfs4_has_persistent_session(clp)) { |
1177 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); | 1207 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); |
1178 | encode_attrs(xdr, arg->u.attrs, arg->server); | 1208 | encode_attrs(xdr, arg->u.attrs, arg->server); |
@@ -1324,14 +1354,14 @@ static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr) | |||
1324 | hdr->replen += decode_putrootfh_maxsz; | 1354 | hdr->replen += decode_putrootfh_maxsz; |
1325 | } | 1355 | } |
1326 | 1356 | ||
1327 | static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx) | 1357 | static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx) |
1328 | { | 1358 | { |
1329 | nfs4_stateid stateid; | 1359 | nfs4_stateid stateid; |
1330 | __be32 *p; | 1360 | __be32 *p; |
1331 | 1361 | ||
1332 | p = reserve_space(xdr, NFS4_STATEID_SIZE); | 1362 | p = reserve_space(xdr, NFS4_STATEID_SIZE); |
1333 | if (ctx->state != NULL) { | 1363 | if (ctx->state != NULL) { |
1334 | nfs4_copy_stateid(&stateid, ctx->state, ctx->lockowner); | 1364 | nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid); |
1335 | xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE); | 1365 | xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE); |
1336 | } else | 1366 | } else |
1337 | xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); | 1367 | xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); |
@@ -1344,7 +1374,7 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, | |||
1344 | p = reserve_space(xdr, 4); | 1374 | p = reserve_space(xdr, 4); |
1345 | *p = cpu_to_be32(OP_READ); | 1375 | *p = cpu_to_be32(OP_READ); |
1346 | 1376 | ||
1347 | encode_stateid(xdr, args->context); | 1377 | encode_stateid(xdr, args->context, args->lock_context); |
1348 | 1378 | ||
1349 | p = reserve_space(xdr, 12); | 1379 | p = reserve_space(xdr, 12); |
1350 | p = xdr_encode_hyper(p, args->offset); | 1380 | p = xdr_encode_hyper(p, args->offset); |
@@ -1523,7 +1553,7 @@ static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *arg | |||
1523 | p = reserve_space(xdr, 4); | 1553 | p = reserve_space(xdr, 4); |
1524 | *p = cpu_to_be32(OP_WRITE); | 1554 | *p = cpu_to_be32(OP_WRITE); |
1525 | 1555 | ||
1526 | encode_stateid(xdr, args->context); | 1556 | encode_stateid(xdr, args->context, args->lock_context); |
1527 | 1557 | ||
1528 | p = reserve_space(xdr, 16); | 1558 | p = reserve_space(xdr, 16); |
1529 | p = xdr_encode_hyper(p, args->offset); | 1559 | p = xdr_encode_hyper(p, args->offset); |
@@ -1704,7 +1734,7 @@ static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args) | |||
1704 | { | 1734 | { |
1705 | #if defined(CONFIG_NFS_V4_1) | 1735 | #if defined(CONFIG_NFS_V4_1) |
1706 | if (args->sa_session) | 1736 | if (args->sa_session) |
1707 | return args->sa_session->clp->cl_minorversion; | 1737 | return args->sa_session->clp->cl_mvops->minor_version; |
1708 | #endif /* CONFIG_NFS_V4_1 */ | 1738 | #endif /* CONFIG_NFS_V4_1 */ |
1709 | return 0; | 1739 | return 0; |
1710 | } | 1740 | } |
@@ -2048,6 +2078,20 @@ static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_ | |||
2048 | return 0; | 2078 | return 0; |
2049 | } | 2079 | } |
2050 | 2080 | ||
2081 | static int nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, __be32 *p, struct nfs_release_lockowner_args *args) | ||
2082 | { | ||
2083 | struct xdr_stream xdr; | ||
2084 | struct compound_hdr hdr = { | ||
2085 | .minorversion = 0, | ||
2086 | }; | ||
2087 | |||
2088 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
2089 | encode_compound_hdr(&xdr, req, &hdr); | ||
2090 | encode_release_lockowner(&xdr, &args->lock_owner, &hdr); | ||
2091 | encode_nops(&hdr); | ||
2092 | return 0; | ||
2093 | } | ||
2094 | |||
2051 | /* | 2095 | /* |
2052 | * Encode a READLINK request | 2096 | * Encode a READLINK request |
2053 | */ | 2097 | */ |
@@ -2395,7 +2439,7 @@ static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p, | |||
2395 | { | 2439 | { |
2396 | struct xdr_stream xdr; | 2440 | struct xdr_stream xdr; |
2397 | struct compound_hdr hdr = { | 2441 | struct compound_hdr hdr = { |
2398 | .minorversion = args->client->cl_minorversion, | 2442 | .minorversion = args->client->cl_mvops->minor_version, |
2399 | }; | 2443 | }; |
2400 | 2444 | ||
2401 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 2445 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
@@ -2413,7 +2457,7 @@ static int nfs4_xdr_enc_create_session(struct rpc_rqst *req, uint32_t *p, | |||
2413 | { | 2457 | { |
2414 | struct xdr_stream xdr; | 2458 | struct xdr_stream xdr; |
2415 | struct compound_hdr hdr = { | 2459 | struct compound_hdr hdr = { |
2416 | .minorversion = args->client->cl_minorversion, | 2460 | .minorversion = args->client->cl_mvops->minor_version, |
2417 | }; | 2461 | }; |
2418 | 2462 | ||
2419 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 2463 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
@@ -2431,7 +2475,7 @@ static int nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, uint32_t *p, | |||
2431 | { | 2475 | { |
2432 | struct xdr_stream xdr; | 2476 | struct xdr_stream xdr; |
2433 | struct compound_hdr hdr = { | 2477 | struct compound_hdr hdr = { |
2434 | .minorversion = session->clp->cl_minorversion, | 2478 | .minorversion = session->clp->cl_mvops->minor_version, |
2435 | }; | 2479 | }; |
2436 | 2480 | ||
2437 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | 2481 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); |
@@ -3973,6 +4017,11 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) | |||
3973 | return status; | 4017 | return status; |
3974 | } | 4018 | } |
3975 | 4019 | ||
4020 | static int decode_release_lockowner(struct xdr_stream *xdr) | ||
4021 | { | ||
4022 | return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER); | ||
4023 | } | ||
4024 | |||
3976 | static int decode_lookup(struct xdr_stream *xdr) | 4025 | static int decode_lookup(struct xdr_stream *xdr) |
3977 | { | 4026 | { |
3978 | return decode_op_hdr(xdr, OP_LOOKUP); | 4027 | return decode_op_hdr(xdr, OP_LOOKUP); |
@@ -5259,6 +5308,19 @@ out: | |||
5259 | return status; | 5308 | return status; |
5260 | } | 5309 | } |
5261 | 5310 | ||
5311 | static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, __be32 *p, void *dummy) | ||
5312 | { | ||
5313 | struct xdr_stream xdr; | ||
5314 | struct compound_hdr hdr; | ||
5315 | int status; | ||
5316 | |||
5317 | xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); | ||
5318 | status = decode_compound_hdr(&xdr, &hdr); | ||
5319 | if (!status) | ||
5320 | status = decode_release_lockowner(&xdr); | ||
5321 | return status; | ||
5322 | } | ||
5323 | |||
5262 | /* | 5324 | /* |
5263 | * Decode READLINK response | 5325 | * Decode READLINK response |
5264 | */ | 5326 | */ |
@@ -5866,6 +5928,7 @@ struct rpc_procinfo nfs4_procedures[] = { | |||
5866 | PROC(GETACL, enc_getacl, dec_getacl), | 5928 | PROC(GETACL, enc_getacl, dec_getacl), |
5867 | PROC(SETACL, enc_setacl, dec_setacl), | 5929 | PROC(SETACL, enc_setacl, dec_setacl), |
5868 | PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), | 5930 | PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), |
5931 | PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), | ||
5869 | #if defined(CONFIG_NFS_V4_1) | 5932 | #if defined(CONFIG_NFS_V4_1) |
5870 | PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), | 5933 | PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), |
5871 | PROC(CREATE_SESSION, enc_create_session, dec_create_session), | 5934 | PROC(CREATE_SESSION, enc_create_session, dec_create_session), |
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c index 6bd19d843af7..df101d9f546a 100644 --- a/fs/nfs/nfsroot.c +++ b/fs/nfs/nfsroot.c | |||
@@ -105,7 +105,7 @@ static char nfs_root_name[256] __initdata = ""; | |||
105 | static __be32 servaddr __initdata = 0; | 105 | static __be32 servaddr __initdata = 0; |
106 | 106 | ||
107 | /* Name of directory to mount */ | 107 | /* Name of directory to mount */ |
108 | static char nfs_export_path[NFS_MAXPATHLEN] __initdata = { 0, }; | 108 | static char nfs_export_path[NFS_MAXPATHLEN + 1] __initdata = { 0, }; |
109 | 109 | ||
110 | /* NFS-related data */ | 110 | /* NFS-related data */ |
111 | static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */ | 111 | static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */ |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index a3654e57b589..919490232e17 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -79,6 +79,7 @@ nfs_create_request(struct nfs_open_context *ctx, struct inode *inode, | |||
79 | req->wb_pgbase = offset; | 79 | req->wb_pgbase = offset; |
80 | req->wb_bytes = count; | 80 | req->wb_bytes = count; |
81 | req->wb_context = get_nfs_open_context(ctx); | 81 | req->wb_context = get_nfs_open_context(ctx); |
82 | req->wb_lock_context = nfs_get_lock_context(ctx); | ||
82 | kref_init(&req->wb_kref); | 83 | kref_init(&req->wb_kref); |
83 | return req; | 84 | return req; |
84 | } | 85 | } |
@@ -141,11 +142,16 @@ void nfs_clear_request(struct nfs_page *req) | |||
141 | { | 142 | { |
142 | struct page *page = req->wb_page; | 143 | struct page *page = req->wb_page; |
143 | struct nfs_open_context *ctx = req->wb_context; | 144 | struct nfs_open_context *ctx = req->wb_context; |
145 | struct nfs_lock_context *l_ctx = req->wb_lock_context; | ||
144 | 146 | ||
145 | if (page != NULL) { | 147 | if (page != NULL) { |
146 | page_cache_release(page); | 148 | page_cache_release(page); |
147 | req->wb_page = NULL; | 149 | req->wb_page = NULL; |
148 | } | 150 | } |
151 | if (l_ctx != NULL) { | ||
152 | nfs_put_lock_context(l_ctx); | ||
153 | req->wb_lock_context = NULL; | ||
154 | } | ||
149 | if (ctx != NULL) { | 155 | if (ctx != NULL) { |
150 | put_nfs_open_context(ctx); | 156 | put_nfs_open_context(ctx); |
151 | req->wb_context = NULL; | 157 | req->wb_context = NULL; |
@@ -235,7 +241,7 @@ static int nfs_can_coalesce_requests(struct nfs_page *prev, | |||
235 | { | 241 | { |
236 | if (req->wb_context->cred != prev->wb_context->cred) | 242 | if (req->wb_context->cred != prev->wb_context->cred) |
237 | return 0; | 243 | return 0; |
238 | if (req->wb_context->lockowner != prev->wb_context->lockowner) | 244 | if (req->wb_lock_context->lockowner != prev->wb_lock_context->lockowner) |
239 | return 0; | 245 | return 0; |
240 | if (req->wb_context->state != prev->wb_context->state) | 246 | if (req->wb_context->state != prev->wb_context->state) |
241 | return 0; | 247 | return 0; |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 6e2b06e6ca79..87adc2744246 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -190,6 +190,7 @@ static int nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
190 | data->args.pages = data->pagevec; | 190 | data->args.pages = data->pagevec; |
191 | data->args.count = count; | 191 | data->args.count = count; |
192 | data->args.context = get_nfs_open_context(req->wb_context); | 192 | data->args.context = get_nfs_open_context(req->wb_context); |
193 | data->args.lock_context = req->wb_lock_context; | ||
193 | 194 | ||
194 | data->res.fattr = &data->fattr; | 195 | data->res.fattr = &data->fattr; |
195 | data->res.count = count; | 196 | data->res.count = count; |
@@ -410,7 +411,7 @@ void nfs_read_prepare(struct rpc_task *task, void *calldata) | |||
410 | { | 411 | { |
411 | struct nfs_read_data *data = calldata; | 412 | struct nfs_read_data *data = calldata; |
412 | 413 | ||
413 | if (nfs4_setup_sequence(NFS_SERVER(data->inode)->nfs_client, | 414 | if (nfs4_setup_sequence(NFS_SERVER(data->inode), |
414 | &data->args.seq_args, &data->res.seq_res, | 415 | &data->args.seq_args, &data->res.seq_res, |
415 | 0, task)) | 416 | 0, task)) |
416 | return; | 417 | return; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index f9df16de4a56..f1ae39f6cb02 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -546,6 +546,9 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, | |||
546 | { | 546 | { |
547 | struct sockaddr *sap = (struct sockaddr *)&nfss->mountd_address; | 547 | struct sockaddr *sap = (struct sockaddr *)&nfss->mountd_address; |
548 | 548 | ||
549 | if (nfss->flags & NFS_MOUNT_LEGACY_INTERFACE) | ||
550 | return; | ||
551 | |||
549 | switch (sap->sa_family) { | 552 | switch (sap->sa_family) { |
550 | case AF_INET: { | 553 | case AF_INET: { |
551 | struct sockaddr_in *sin = (struct sockaddr_in *)sap; | 554 | struct sockaddr_in *sin = (struct sockaddr_in *)sap; |
@@ -1780,6 +1783,7 @@ static int nfs_validate_mount_data(void *options, | |||
1780 | * can deal with. | 1783 | * can deal with. |
1781 | */ | 1784 | */ |
1782 | args->flags = data->flags & NFS_MOUNT_FLAGMASK; | 1785 | args->flags = data->flags & NFS_MOUNT_FLAGMASK; |
1786 | args->flags |= NFS_MOUNT_LEGACY_INTERFACE; | ||
1783 | args->rsize = data->rsize; | 1787 | args->rsize = data->rsize; |
1784 | args->wsize = data->wsize; | 1788 | args->wsize = data->wsize; |
1785 | args->timeo = data->timeo; | 1789 | args->timeo = data->timeo; |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index a2242af6a17d..2f84adaad427 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
@@ -110,7 +110,7 @@ void nfs_unlink_prepare(struct rpc_task *task, void *calldata) | |||
110 | struct nfs_unlinkdata *data = calldata; | 110 | struct nfs_unlinkdata *data = calldata; |
111 | struct nfs_server *server = NFS_SERVER(data->dir); | 111 | struct nfs_server *server = NFS_SERVER(data->dir); |
112 | 112 | ||
113 | if (nfs4_setup_sequence(server->nfs_client, &data->args.seq_args, | 113 | if (nfs4_setup_sequence(server, &data->args.seq_args, |
114 | &data->res.seq_res, 1, task)) | 114 | &data->res.seq_res, 1, task)) |
115 | return; | 115 | return; |
116 | rpc_call_start(task); | 116 | rpc_call_start(task); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 91679e2631ee..874972d9427c 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -222,7 +222,7 @@ static void nfs_end_page_writeback(struct page *page) | |||
222 | clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); | 222 | clear_bdi_congested(&nfss->backing_dev_info, BLK_RW_ASYNC); |
223 | } | 223 | } |
224 | 224 | ||
225 | static struct nfs_page *nfs_find_and_lock_request(struct page *page) | 225 | static struct nfs_page *nfs_find_and_lock_request(struct page *page, bool nonblock) |
226 | { | 226 | { |
227 | struct inode *inode = page->mapping->host; | 227 | struct inode *inode = page->mapping->host; |
228 | struct nfs_page *req; | 228 | struct nfs_page *req; |
@@ -241,7 +241,10 @@ static struct nfs_page *nfs_find_and_lock_request(struct page *page) | |||
241 | * request as dirty (in which case we don't care). | 241 | * request as dirty (in which case we don't care). |
242 | */ | 242 | */ |
243 | spin_unlock(&inode->i_lock); | 243 | spin_unlock(&inode->i_lock); |
244 | ret = nfs_wait_on_request(req); | 244 | if (!nonblock) |
245 | ret = nfs_wait_on_request(req); | ||
246 | else | ||
247 | ret = -EAGAIN; | ||
245 | nfs_release_request(req); | 248 | nfs_release_request(req); |
246 | if (ret != 0) | 249 | if (ret != 0) |
247 | return ERR_PTR(ret); | 250 | return ERR_PTR(ret); |
@@ -256,12 +259,12 @@ static struct nfs_page *nfs_find_and_lock_request(struct page *page) | |||
256 | * May return an error if the user signalled nfs_wait_on_request(). | 259 | * May return an error if the user signalled nfs_wait_on_request(). |
257 | */ | 260 | */ |
258 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, | 261 | static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio, |
259 | struct page *page) | 262 | struct page *page, bool nonblock) |
260 | { | 263 | { |
261 | struct nfs_page *req; | 264 | struct nfs_page *req; |
262 | int ret = 0; | 265 | int ret = 0; |
263 | 266 | ||
264 | req = nfs_find_and_lock_request(page); | 267 | req = nfs_find_and_lock_request(page, nonblock); |
265 | if (!req) | 268 | if (!req) |
266 | goto out; | 269 | goto out; |
267 | ret = PTR_ERR(req); | 270 | ret = PTR_ERR(req); |
@@ -283,12 +286,20 @@ out: | |||
283 | static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) | 286 | static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, struct nfs_pageio_descriptor *pgio) |
284 | { | 287 | { |
285 | struct inode *inode = page->mapping->host; | 288 | struct inode *inode = page->mapping->host; |
289 | int ret; | ||
286 | 290 | ||
287 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); | 291 | nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE); |
288 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); | 292 | nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1); |
289 | 293 | ||
290 | nfs_pageio_cond_complete(pgio, page->index); | 294 | nfs_pageio_cond_complete(pgio, page->index); |
291 | return nfs_page_async_flush(pgio, page); | 295 | ret = nfs_page_async_flush(pgio, page, |
296 | wbc->sync_mode == WB_SYNC_NONE || | ||
297 | wbc->nonblocking != 0); | ||
298 | if (ret == -EAGAIN) { | ||
299 | redirty_page_for_writepage(wbc, page); | ||
300 | ret = 0; | ||
301 | } | ||
302 | return ret; | ||
292 | } | 303 | } |
293 | 304 | ||
294 | /* | 305 | /* |
@@ -689,7 +700,9 @@ int nfs_flush_incompatible(struct file *file, struct page *page) | |||
689 | req = nfs_page_find_request(page); | 700 | req = nfs_page_find_request(page); |
690 | if (req == NULL) | 701 | if (req == NULL) |
691 | return 0; | 702 | return 0; |
692 | do_flush = req->wb_page != page || req->wb_context != ctx; | 703 | do_flush = req->wb_page != page || req->wb_context != ctx || |
704 | req->wb_lock_context->lockowner != current->files || | ||
705 | req->wb_lock_context->pid != current->tgid; | ||
693 | nfs_release_request(req); | 706 | nfs_release_request(req); |
694 | if (!do_flush) | 707 | if (!do_flush) |
695 | return 0; | 708 | return 0; |
@@ -813,6 +826,7 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
813 | data->args.pages = data->pagevec; | 826 | data->args.pages = data->pagevec; |
814 | data->args.count = count; | 827 | data->args.count = count; |
815 | data->args.context = get_nfs_open_context(req->wb_context); | 828 | data->args.context = get_nfs_open_context(req->wb_context); |
829 | data->args.lock_context = req->wb_lock_context; | ||
816 | data->args.stable = NFS_UNSTABLE; | 830 | data->args.stable = NFS_UNSTABLE; |
817 | if (how & FLUSH_STABLE) { | 831 | if (how & FLUSH_STABLE) { |
818 | data->args.stable = NFS_DATA_SYNC; | 832 | data->args.stable = NFS_DATA_SYNC; |
@@ -1036,9 +1050,9 @@ out: | |||
1036 | void nfs_write_prepare(struct rpc_task *task, void *calldata) | 1050 | void nfs_write_prepare(struct rpc_task *task, void *calldata) |
1037 | { | 1051 | { |
1038 | struct nfs_write_data *data = calldata; | 1052 | struct nfs_write_data *data = calldata; |
1039 | struct nfs_client *clp = (NFS_SERVER(data->inode))->nfs_client; | ||
1040 | 1053 | ||
1041 | if (nfs4_setup_sequence(clp, &data->args.seq_args, | 1054 | if (nfs4_setup_sequence(NFS_SERVER(data->inode), |
1055 | &data->args.seq_args, | ||
1042 | &data->res.seq_res, 1, task)) | 1056 | &data->res.seq_res, 1, task)) |
1043 | return; | 1057 | return; |
1044 | rpc_call_start(task); | 1058 | rpc_call_start(task); |
@@ -1379,7 +1393,7 @@ static const struct rpc_call_ops nfs_commit_ops = { | |||
1379 | .rpc_release = nfs_commit_release, | 1393 | .rpc_release = nfs_commit_release, |
1380 | }; | 1394 | }; |
1381 | 1395 | ||
1382 | static int nfs_commit_inode(struct inode *inode, int how) | 1396 | int nfs_commit_inode(struct inode *inode, int how) |
1383 | { | 1397 | { |
1384 | LIST_HEAD(head); | 1398 | LIST_HEAD(head); |
1385 | int may_wait = how & FLUSH_SYNC; | 1399 | int may_wait = how & FLUSH_SYNC; |
@@ -1443,11 +1457,6 @@ out_mark_dirty: | |||
1443 | return ret; | 1457 | return ret; |
1444 | } | 1458 | } |
1445 | #else | 1459 | #else |
1446 | static int nfs_commit_inode(struct inode *inode, int how) | ||
1447 | { | ||
1448 | return 0; | ||
1449 | } | ||
1450 | |||
1451 | static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc) | 1460 | static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_control *wbc) |
1452 | { | 1461 | { |
1453 | return 0; | 1462 | return 0; |
@@ -1546,7 +1555,7 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage, | |||
1546 | 1555 | ||
1547 | nfs_fscache_release_page(page, GFP_KERNEL); | 1556 | nfs_fscache_release_page(page, GFP_KERNEL); |
1548 | 1557 | ||
1549 | req = nfs_find_and_lock_request(page); | 1558 | req = nfs_find_and_lock_request(page, false); |
1550 | ret = PTR_ERR(req); | 1559 | ret = PTR_ERR(req); |
1551 | if (IS_ERR(req)) | 1560 | if (IS_ERR(req)) |
1552 | goto out; | 1561 | goto out; |
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 3d68f45a37b9..5b7e3021e06b 100644 --- a/fs/nfsd/nfs3proc.c +++ b/fs/nfsd/nfs3proc.c | |||
@@ -168,7 +168,7 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp, | |||
168 | svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4); | 168 | svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4); |
169 | 169 | ||
170 | fh_copy(&resp->fh, &argp->fh); | 170 | fh_copy(&resp->fh, &argp->fh); |
171 | nfserr = nfsd_read(rqstp, &resp->fh, NULL, | 171 | nfserr = nfsd_read(rqstp, &resp->fh, |
172 | argp->offset, | 172 | argp->offset, |
173 | rqstp->rq_vec, argp->vlen, | 173 | rqstp->rq_vec, argp->vlen, |
174 | &resp->count); | 174 | &resp->count); |
@@ -271,7 +271,7 @@ nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, | |||
271 | fh_init(&resp->fh, NFS3_FHSIZE); | 271 | fh_init(&resp->fh, NFS3_FHSIZE); |
272 | nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, | 272 | nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, |
273 | &argp->attrs, S_IFDIR, 0, &resp->fh); | 273 | &argp->attrs, S_IFDIR, 0, &resp->fh); |
274 | 274 | fh_unlock(&resp->dirfh); | |
275 | RETURN_STATUS(nfserr); | 275 | RETURN_STATUS(nfserr); |
276 | } | 276 | } |
277 | 277 | ||
@@ -327,7 +327,7 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp, | |||
327 | type = nfs3_ftypes[argp->ftype]; | 327 | type = nfs3_ftypes[argp->ftype]; |
328 | nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, | 328 | nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, |
329 | &argp->attrs, type, rdev, &resp->fh); | 329 | &argp->attrs, type, rdev, &resp->fh); |
330 | 330 | fh_unlock(&resp->dirfh); | |
331 | RETURN_STATUS(nfserr); | 331 | RETURN_STATUS(nfserr); |
332 | } | 332 | } |
333 | 333 | ||
@@ -348,6 +348,7 @@ nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, | |||
348 | /* Unlink. -S_IFDIR means file must not be a directory */ | 348 | /* Unlink. -S_IFDIR means file must not be a directory */ |
349 | fh_copy(&resp->fh, &argp->fh); | 349 | fh_copy(&resp->fh, &argp->fh); |
350 | nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len); | 350 | nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len); |
351 | fh_unlock(&resp->fh); | ||
351 | RETURN_STATUS(nfserr); | 352 | RETURN_STATUS(nfserr); |
352 | } | 353 | } |
353 | 354 | ||
@@ -367,6 +368,7 @@ nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, | |||
367 | 368 | ||
368 | fh_copy(&resp->fh, &argp->fh); | 369 | fh_copy(&resp->fh, &argp->fh); |
369 | nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len); | 370 | nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len); |
371 | fh_unlock(&resp->fh); | ||
370 | RETURN_STATUS(nfserr); | 372 | RETURN_STATUS(nfserr); |
371 | } | 373 | } |
372 | 374 | ||
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index eb78e7e22077..988cbb3a19b6 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -143,8 +143,6 @@ struct nfs4_cb_compound_hdr { | |||
143 | u32 minorversion; | 143 | u32 minorversion; |
144 | /* res */ | 144 | /* res */ |
145 | int status; | 145 | int status; |
146 | u32 taglen; | ||
147 | char *tag; | ||
148 | }; | 146 | }; |
149 | 147 | ||
150 | static struct { | 148 | static struct { |
@@ -205,6 +203,16 @@ nfs_cb_stat_to_errno(int stat) | |||
205 | */ | 203 | */ |
206 | 204 | ||
207 | static void | 205 | static void |
206 | encode_stateid(struct xdr_stream *xdr, stateid_t *sid) | ||
207 | { | ||
208 | __be32 *p; | ||
209 | |||
210 | RESERVE_SPACE(sizeof(stateid_t)); | ||
211 | WRITE32(sid->si_generation); | ||
212 | WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); | ||
213 | } | ||
214 | |||
215 | static void | ||
208 | encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) | 216 | encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) |
209 | { | 217 | { |
210 | __be32 * p; | 218 | __be32 * p; |
@@ -229,10 +237,10 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp, | |||
229 | __be32 *p; | 237 | __be32 *p; |
230 | int len = dp->dl_fh.fh_size; | 238 | int len = dp->dl_fh.fh_size; |
231 | 239 | ||
232 | RESERVE_SPACE(12+sizeof(dp->dl_stateid) + len); | 240 | RESERVE_SPACE(4); |
233 | WRITE32(OP_CB_RECALL); | 241 | WRITE32(OP_CB_RECALL); |
234 | WRITE32(dp->dl_stateid.si_generation); | 242 | encode_stateid(xdr, &dp->dl_stateid); |
235 | WRITEMEM(&dp->dl_stateid.si_opaque, sizeof(stateid_opaque_t)); | 243 | RESERVE_SPACE(8 + (XDR_QUADLEN(len) << 2)); |
236 | WRITE32(0); /* truncate optimization not implemented */ | 244 | WRITE32(0); /* truncate optimization not implemented */ |
237 | WRITE32(len); | 245 | WRITE32(len); |
238 | WRITEMEM(&dp->dl_fh.fh_base, len); | 246 | WRITEMEM(&dp->dl_fh.fh_base, len); |
@@ -293,13 +301,14 @@ nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, | |||
293 | static int | 301 | static int |
294 | decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){ | 302 | decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){ |
295 | __be32 *p; | 303 | __be32 *p; |
304 | u32 taglen; | ||
296 | 305 | ||
297 | READ_BUF(8); | 306 | READ_BUF(8); |
298 | READ32(hdr->status); | 307 | READ32(hdr->status); |
299 | READ32(hdr->taglen); | 308 | /* We've got no use for the tag; ignore it: */ |
300 | READ_BUF(hdr->taglen + 4); | 309 | READ32(taglen); |
301 | hdr->tag = (char *)p; | 310 | READ_BUF(taglen + 4); |
302 | p += XDR_QUADLEN(hdr->taglen); | 311 | p += XDR_QUADLEN(taglen); |
303 | READ32(hdr->nops); | 312 | READ32(hdr->nops); |
304 | return 0; | 313 | return 0; |
305 | } | 314 | } |
@@ -667,28 +676,28 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) | |||
667 | } | 676 | } |
668 | 677 | ||
669 | switch (task->tk_status) { | 678 | switch (task->tk_status) { |
670 | case -EIO: | 679 | case 0: |
680 | return; | ||
681 | case -EBADHANDLE: | ||
682 | case -NFS4ERR_BAD_STATEID: | ||
683 | /* Race: client probably got cb_recall | ||
684 | * before open reply granting delegation */ | ||
685 | break; | ||
686 | default: | ||
671 | /* Network partition? */ | 687 | /* Network partition? */ |
672 | atomic_set(&clp->cl_cb_set, 0); | 688 | atomic_set(&clp->cl_cb_set, 0); |
673 | warn_no_callback_path(clp, task->tk_status); | 689 | warn_no_callback_path(clp, task->tk_status); |
674 | if (current_rpc_client != task->tk_client) { | 690 | if (current_rpc_client != task->tk_client) { |
675 | /* queue a callback on the new connection: */ | 691 | /* queue a callback on the new connection: */ |
692 | atomic_inc(&dp->dl_count); | ||
676 | nfsd4_cb_recall(dp); | 693 | nfsd4_cb_recall(dp); |
677 | return; | 694 | return; |
678 | } | 695 | } |
679 | case -EBADHANDLE: | ||
680 | case -NFS4ERR_BAD_STATEID: | ||
681 | /* Race: client probably got cb_recall | ||
682 | * before open reply granting delegation */ | ||
683 | break; | ||
684 | default: | ||
685 | /* success, or error we can't handle */ | ||
686 | return; | ||
687 | } | 696 | } |
688 | if (dp->dl_retries--) { | 697 | if (dp->dl_retries--) { |
689 | rpc_delay(task, 2*HZ); | 698 | rpc_delay(task, 2*HZ); |
690 | task->tk_status = 0; | 699 | task->tk_status = 0; |
691 | rpc_restart_call(task); | 700 | rpc_restart_call_prepare(task); |
692 | return; | 701 | return; |
693 | } else { | 702 | } else { |
694 | atomic_set(&clp->cl_cb_set, 0); | 703 | atomic_set(&clp->cl_cb_set, 0); |
@@ -752,18 +761,16 @@ static void _nfsd4_cb_recall(struct nfs4_delegation *dp) | |||
752 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL], | 761 | .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL], |
753 | .rpc_cred = callback_cred | 762 | .rpc_cred = callback_cred |
754 | }; | 763 | }; |
755 | int status; | ||
756 | 764 | ||
757 | if (clnt == NULL) | 765 | if (clnt == NULL) { |
766 | nfs4_put_delegation(dp); | ||
758 | return; /* Client is shutting down; give up. */ | 767 | return; /* Client is shutting down; give up. */ |
768 | } | ||
759 | 769 | ||
760 | args->args_op = dp; | 770 | args->args_op = dp; |
761 | msg.rpc_argp = args; | 771 | msg.rpc_argp = args; |
762 | dp->dl_retries = 1; | 772 | dp->dl_retries = 1; |
763 | status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT, | 773 | rpc_call_async(clnt, &msg, RPC_TASK_SOFT, &nfsd4_cb_recall_ops, dp); |
764 | &nfsd4_cb_recall_ops, dp); | ||
765 | if (status) | ||
766 | nfs4_put_delegation(dp); | ||
767 | } | 774 | } |
768 | 775 | ||
769 | void nfsd4_do_callback_rpc(struct work_struct *w) | 776 | void nfsd4_do_callback_rpc(struct work_struct *w) |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 4a2734758778..2e7357104cfd 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -51,7 +51,6 @@ static time_t boot_time; | |||
51 | static u32 current_ownerid = 1; | 51 | static u32 current_ownerid = 1; |
52 | static u32 current_fileid = 1; | 52 | static u32 current_fileid = 1; |
53 | static u32 current_delegid = 1; | 53 | static u32 current_delegid = 1; |
54 | static u32 nfs4_init; | ||
55 | static stateid_t zerostateid; /* bits all 0 */ | 54 | static stateid_t zerostateid; /* bits all 0 */ |
56 | static stateid_t onestateid; /* bits all 1 */ | 55 | static stateid_t onestateid; /* bits all 1 */ |
57 | static u64 current_sessionid = 1; | 56 | static u64 current_sessionid = 1; |
@@ -163,6 +162,46 @@ static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE]; | |||
163 | static struct list_head file_hashtbl[FILE_HASH_SIZE]; | 162 | static struct list_head file_hashtbl[FILE_HASH_SIZE]; |
164 | static struct list_head stateid_hashtbl[STATEID_HASH_SIZE]; | 163 | static struct list_head stateid_hashtbl[STATEID_HASH_SIZE]; |
165 | 164 | ||
165 | static void __nfs4_file_get_access(struct nfs4_file *fp, int oflag) | ||
166 | { | ||
167 | BUG_ON(!(fp->fi_fds[oflag] || fp->fi_fds[O_RDWR])); | ||
168 | atomic_inc(&fp->fi_access[oflag]); | ||
169 | } | ||
170 | |||
171 | static void nfs4_file_get_access(struct nfs4_file *fp, int oflag) | ||
172 | { | ||
173 | if (oflag == O_RDWR) { | ||
174 | __nfs4_file_get_access(fp, O_RDONLY); | ||
175 | __nfs4_file_get_access(fp, O_WRONLY); | ||
176 | } else | ||
177 | __nfs4_file_get_access(fp, oflag); | ||
178 | } | ||
179 | |||
180 | static void nfs4_file_put_fd(struct nfs4_file *fp, int oflag) | ||
181 | { | ||
182 | if (fp->fi_fds[oflag]) { | ||
183 | fput(fp->fi_fds[oflag]); | ||
184 | fp->fi_fds[oflag] = NULL; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag) | ||
189 | { | ||
190 | if (atomic_dec_and_test(&fp->fi_access[oflag])) { | ||
191 | nfs4_file_put_fd(fp, O_RDWR); | ||
192 | nfs4_file_put_fd(fp, oflag); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static void nfs4_file_put_access(struct nfs4_file *fp, int oflag) | ||
197 | { | ||
198 | if (oflag == O_RDWR) { | ||
199 | __nfs4_file_put_access(fp, O_RDONLY); | ||
200 | __nfs4_file_put_access(fp, O_WRONLY); | ||
201 | } else | ||
202 | __nfs4_file_put_access(fp, oflag); | ||
203 | } | ||
204 | |||
166 | static struct nfs4_delegation * | 205 | static struct nfs4_delegation * |
167 | alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type) | 206 | alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type) |
168 | { | 207 | { |
@@ -171,6 +210,13 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f | |||
171 | struct nfs4_cb_conn *cb = &stp->st_stateowner->so_client->cl_cb_conn; | 210 | struct nfs4_cb_conn *cb = &stp->st_stateowner->so_client->cl_cb_conn; |
172 | 211 | ||
173 | dprintk("NFSD alloc_init_deleg\n"); | 212 | dprintk("NFSD alloc_init_deleg\n"); |
213 | /* | ||
214 | * Major work on the lease subsystem (for example, to support | ||
215 | * calbacks on stat) will be required before we can support | ||
216 | * write delegations properly. | ||
217 | */ | ||
218 | if (type != NFS4_OPEN_DELEGATE_READ) | ||
219 | return NULL; | ||
174 | if (fp->fi_had_conflict) | 220 | if (fp->fi_had_conflict) |
175 | return NULL; | 221 | return NULL; |
176 | if (num_delegations > max_delegations) | 222 | if (num_delegations > max_delegations) |
@@ -185,9 +231,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f | |||
185 | dp->dl_client = clp; | 231 | dp->dl_client = clp; |
186 | get_nfs4_file(fp); | 232 | get_nfs4_file(fp); |
187 | dp->dl_file = fp; | 233 | dp->dl_file = fp; |
234 | nfs4_file_get_access(fp, O_RDONLY); | ||
188 | dp->dl_flock = NULL; | 235 | dp->dl_flock = NULL; |
189 | get_file(stp->st_vfs_file); | ||
190 | dp->dl_vfs_file = stp->st_vfs_file; | ||
191 | dp->dl_type = type; | 236 | dp->dl_type = type; |
192 | dp->dl_ident = cb->cb_ident; | 237 | dp->dl_ident = cb->cb_ident; |
193 | dp->dl_stateid.si_boot = boot_time; | 238 | dp->dl_stateid.si_boot = boot_time; |
@@ -222,15 +267,12 @@ nfs4_put_delegation(struct nfs4_delegation *dp) | |||
222 | static void | 267 | static void |
223 | nfs4_close_delegation(struct nfs4_delegation *dp) | 268 | nfs4_close_delegation(struct nfs4_delegation *dp) |
224 | { | 269 | { |
225 | struct file *filp = dp->dl_vfs_file; | 270 | struct file *filp = find_readable_file(dp->dl_file); |
226 | 271 | ||
227 | dprintk("NFSD: close_delegation dp %p\n",dp); | 272 | dprintk("NFSD: close_delegation dp %p\n",dp); |
228 | dp->dl_vfs_file = NULL; | ||
229 | /* The following nfsd_close may not actually close the file, | ||
230 | * but we want to remove the lease in any case. */ | ||
231 | if (dp->dl_flock) | 273 | if (dp->dl_flock) |
232 | vfs_setlease(filp, F_UNLCK, &dp->dl_flock); | 274 | vfs_setlease(filp, F_UNLCK, &dp->dl_flock); |
233 | nfsd_close(filp); | 275 | nfs4_file_put_access(dp->dl_file, O_RDONLY); |
234 | } | 276 | } |
235 | 277 | ||
236 | /* Called under the state lock. */ | 278 | /* Called under the state lock. */ |
@@ -302,8 +344,12 @@ static void free_generic_stateid(struct nfs4_stateid *stp) | |||
302 | 344 | ||
303 | static void release_lock_stateid(struct nfs4_stateid *stp) | 345 | static void release_lock_stateid(struct nfs4_stateid *stp) |
304 | { | 346 | { |
347 | struct file *file; | ||
348 | |||
305 | unhash_generic_stateid(stp); | 349 | unhash_generic_stateid(stp); |
306 | locks_remove_posix(stp->st_vfs_file, (fl_owner_t)stp->st_stateowner); | 350 | file = find_any_file(stp->st_file); |
351 | if (file) | ||
352 | locks_remove_posix(file, (fl_owner_t)stp->st_stateowner); | ||
307 | free_generic_stateid(stp); | 353 | free_generic_stateid(stp); |
308 | } | 354 | } |
309 | 355 | ||
@@ -341,11 +387,85 @@ release_stateid_lockowners(struct nfs4_stateid *open_stp) | |||
341 | } | 387 | } |
342 | } | 388 | } |
343 | 389 | ||
390 | /* | ||
391 | * We store the NONE, READ, WRITE, and BOTH bits separately in the | ||
392 | * st_{access,deny}_bmap field of the stateid, in order to track not | ||
393 | * only what share bits are currently in force, but also what | ||
394 | * combinations of share bits previous opens have used. This allows us | ||
395 | * to enforce the recommendation of rfc 3530 14.2.19 that the server | ||
396 | * return an error if the client attempt to downgrade to a combination | ||
397 | * of share bits not explicable by closing some of its previous opens. | ||
398 | * | ||
399 | * XXX: This enforcement is actually incomplete, since we don't keep | ||
400 | * track of access/deny bit combinations; so, e.g., we allow: | ||
401 | * | ||
402 | * OPEN allow read, deny write | ||
403 | * OPEN allow both, deny none | ||
404 | * DOWNGRADE allow read, deny none | ||
405 | * | ||
406 | * which we should reject. | ||
407 | */ | ||
408 | static void | ||
409 | set_access(unsigned int *access, unsigned long bmap) { | ||
410 | int i; | ||
411 | |||
412 | *access = 0; | ||
413 | for (i = 1; i < 4; i++) { | ||
414 | if (test_bit(i, &bmap)) | ||
415 | *access |= i; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | static void | ||
420 | set_deny(unsigned int *deny, unsigned long bmap) { | ||
421 | int i; | ||
422 | |||
423 | *deny = 0; | ||
424 | for (i = 0; i < 4; i++) { | ||
425 | if (test_bit(i, &bmap)) | ||
426 | *deny |= i ; | ||
427 | } | ||
428 | } | ||
429 | |||
430 | static int | ||
431 | test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) { | ||
432 | unsigned int access, deny; | ||
433 | |||
434 | set_access(&access, stp->st_access_bmap); | ||
435 | set_deny(&deny, stp->st_deny_bmap); | ||
436 | if ((access & open->op_share_deny) || (deny & open->op_share_access)) | ||
437 | return 0; | ||
438 | return 1; | ||
439 | } | ||
440 | |||
441 | static int nfs4_access_to_omode(u32 access) | ||
442 | { | ||
443 | switch (access) { | ||
444 | case NFS4_SHARE_ACCESS_READ: | ||
445 | return O_RDONLY; | ||
446 | case NFS4_SHARE_ACCESS_WRITE: | ||
447 | return O_WRONLY; | ||
448 | case NFS4_SHARE_ACCESS_BOTH: | ||
449 | return O_RDWR; | ||
450 | } | ||
451 | BUG(); | ||
452 | } | ||
453 | |||
454 | static int nfs4_access_bmap_to_omode(struct nfs4_stateid *stp) | ||
455 | { | ||
456 | unsigned int access; | ||
457 | |||
458 | set_access(&access, stp->st_access_bmap); | ||
459 | return nfs4_access_to_omode(access); | ||
460 | } | ||
461 | |||
344 | static void release_open_stateid(struct nfs4_stateid *stp) | 462 | static void release_open_stateid(struct nfs4_stateid *stp) |
345 | { | 463 | { |
464 | int oflag = nfs4_access_bmap_to_omode(stp); | ||
465 | |||
346 | unhash_generic_stateid(stp); | 466 | unhash_generic_stateid(stp); |
347 | release_stateid_lockowners(stp); | 467 | release_stateid_lockowners(stp); |
348 | nfsd_close(stp->st_vfs_file); | 468 | nfs4_file_put_access(stp->st_file, oflag); |
349 | free_generic_stateid(stp); | 469 | free_generic_stateid(stp); |
350 | } | 470 | } |
351 | 471 | ||
@@ -457,7 +577,7 @@ static int set_forechannel_drc_size(struct nfsd4_channel_attrs *fchan) | |||
457 | spin_unlock(&nfsd_drc_lock); | 577 | spin_unlock(&nfsd_drc_lock); |
458 | 578 | ||
459 | if (fchan->maxreqs == 0) | 579 | if (fchan->maxreqs == 0) |
460 | return nfserr_serverfault; | 580 | return nfserr_jukebox; |
461 | 581 | ||
462 | fchan->maxresp_cached = size + NFSD_MIN_HDR_SEQ_SZ; | 582 | fchan->maxresp_cached = size + NFSD_MIN_HDR_SEQ_SZ; |
463 | return 0; | 583 | return 0; |
@@ -542,7 +662,7 @@ alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, | |||
542 | BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot) | 662 | BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot) |
543 | + sizeof(struct nfsd4_session) > PAGE_SIZE); | 663 | + sizeof(struct nfsd4_session) > PAGE_SIZE); |
544 | 664 | ||
545 | status = nfserr_serverfault; | 665 | status = nfserr_jukebox; |
546 | /* allocate struct nfsd4_session and slot table pointers in one piece */ | 666 | /* allocate struct nfsd4_session and slot table pointers in one piece */ |
547 | slotsize = tmp.se_fchannel.maxreqs * sizeof(struct nfsd4_slot *); | 667 | slotsize = tmp.se_fchannel.maxreqs * sizeof(struct nfsd4_slot *); |
548 | new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL); | 668 | new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL); |
@@ -591,10 +711,8 @@ find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid) | |||
591 | 711 | ||
592 | dump_sessionid(__func__, sessionid); | 712 | dump_sessionid(__func__, sessionid); |
593 | idx = hash_sessionid(sessionid); | 713 | idx = hash_sessionid(sessionid); |
594 | dprintk("%s: idx is %d\n", __func__, idx); | ||
595 | /* Search in the appropriate list */ | 714 | /* Search in the appropriate list */ |
596 | list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) { | 715 | list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) { |
597 | dump_sessionid("list traversal", &elem->se_sessionid); | ||
598 | if (!memcmp(elem->se_sessionid.data, sessionid->data, | 716 | if (!memcmp(elem->se_sessionid.data, sessionid->data, |
599 | NFS4_MAX_SESSIONID_LEN)) { | 717 | NFS4_MAX_SESSIONID_LEN)) { |
600 | return elem; | 718 | return elem; |
@@ -714,7 +832,6 @@ release_session_client(struct nfsd4_session *session) | |||
714 | } else | 832 | } else |
715 | renew_client_locked(clp); | 833 | renew_client_locked(clp); |
716 | spin_unlock(&client_lock); | 834 | spin_unlock(&client_lock); |
717 | nfsd4_put_session(session); | ||
718 | } | 835 | } |
719 | 836 | ||
720 | /* must be called under the client_lock */ | 837 | /* must be called under the client_lock */ |
@@ -1220,7 +1337,7 @@ out_new: | |||
1220 | /* Normal case */ | 1337 | /* Normal case */ |
1221 | new = create_client(exid->clname, dname, rqstp, &verf); | 1338 | new = create_client(exid->clname, dname, rqstp, &verf); |
1222 | if (new == NULL) { | 1339 | if (new == NULL) { |
1223 | status = nfserr_serverfault; | 1340 | status = nfserr_jukebox; |
1224 | goto out; | 1341 | goto out; |
1225 | } | 1342 | } |
1226 | 1343 | ||
@@ -1760,6 +1877,8 @@ alloc_init_file(struct inode *ino) | |||
1760 | fp->fi_inode = igrab(ino); | 1877 | fp->fi_inode = igrab(ino); |
1761 | fp->fi_id = current_fileid++; | 1878 | fp->fi_id = current_fileid++; |
1762 | fp->fi_had_conflict = false; | 1879 | fp->fi_had_conflict = false; |
1880 | memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); | ||
1881 | memset(fp->fi_access, 0, sizeof(fp->fi_access)); | ||
1763 | spin_lock(&recall_lock); | 1882 | spin_lock(&recall_lock); |
1764 | list_add(&fp->fi_hash, &file_hashtbl[hashval]); | 1883 | list_add(&fp->fi_hash, &file_hashtbl[hashval]); |
1765 | spin_unlock(&recall_lock); | 1884 | spin_unlock(&recall_lock); |
@@ -1971,57 +2090,6 @@ static inline int deny_valid(u32 x) | |||
1971 | } | 2090 | } |
1972 | 2091 | ||
1973 | /* | 2092 | /* |
1974 | * We store the NONE, READ, WRITE, and BOTH bits separately in the | ||
1975 | * st_{access,deny}_bmap field of the stateid, in order to track not | ||
1976 | * only what share bits are currently in force, but also what | ||
1977 | * combinations of share bits previous opens have used. This allows us | ||
1978 | * to enforce the recommendation of rfc 3530 14.2.19 that the server | ||
1979 | * return an error if the client attempt to downgrade to a combination | ||
1980 | * of share bits not explicable by closing some of its previous opens. | ||
1981 | * | ||
1982 | * XXX: This enforcement is actually incomplete, since we don't keep | ||
1983 | * track of access/deny bit combinations; so, e.g., we allow: | ||
1984 | * | ||
1985 | * OPEN allow read, deny write | ||
1986 | * OPEN allow both, deny none | ||
1987 | * DOWNGRADE allow read, deny none | ||
1988 | * | ||
1989 | * which we should reject. | ||
1990 | */ | ||
1991 | static void | ||
1992 | set_access(unsigned int *access, unsigned long bmap) { | ||
1993 | int i; | ||
1994 | |||
1995 | *access = 0; | ||
1996 | for (i = 1; i < 4; i++) { | ||
1997 | if (test_bit(i, &bmap)) | ||
1998 | *access |= i; | ||
1999 | } | ||
2000 | } | ||
2001 | |||
2002 | static void | ||
2003 | set_deny(unsigned int *deny, unsigned long bmap) { | ||
2004 | int i; | ||
2005 | |||
2006 | *deny = 0; | ||
2007 | for (i = 0; i < 4; i++) { | ||
2008 | if (test_bit(i, &bmap)) | ||
2009 | *deny |= i ; | ||
2010 | } | ||
2011 | } | ||
2012 | |||
2013 | static int | ||
2014 | test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) { | ||
2015 | unsigned int access, deny; | ||
2016 | |||
2017 | set_access(&access, stp->st_access_bmap); | ||
2018 | set_deny(&deny, stp->st_deny_bmap); | ||
2019 | if ((access & open->op_share_deny) || (deny & open->op_share_access)) | ||
2020 | return 0; | ||
2021 | return 1; | ||
2022 | } | ||
2023 | |||
2024 | /* | ||
2025 | * Called to check deny when READ with all zero stateid or | 2093 | * Called to check deny when READ with all zero stateid or |
2026 | * WRITE with all zero or all one stateid | 2094 | * WRITE with all zero or all one stateid |
2027 | */ | 2095 | */ |
@@ -2052,14 +2120,12 @@ out: | |||
2052 | } | 2120 | } |
2053 | 2121 | ||
2054 | static inline void | 2122 | static inline void |
2055 | nfs4_file_downgrade(struct file *filp, unsigned int share_access) | 2123 | nfs4_file_downgrade(struct nfs4_file *fp, unsigned int share_access) |
2056 | { | 2124 | { |
2057 | if (share_access & NFS4_SHARE_ACCESS_WRITE) { | 2125 | if (share_access & NFS4_SHARE_ACCESS_WRITE) |
2058 | drop_file_write_access(filp); | 2126 | nfs4_file_put_access(fp, O_WRONLY); |
2059 | spin_lock(&filp->f_lock); | 2127 | if (share_access & NFS4_SHARE_ACCESS_READ) |
2060 | filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE; | 2128 | nfs4_file_put_access(fp, O_RDONLY); |
2061 | spin_unlock(&filp->f_lock); | ||
2062 | } | ||
2063 | } | 2129 | } |
2064 | 2130 | ||
2065 | /* | 2131 | /* |
@@ -2255,6 +2321,13 @@ find_delegation_file(struct nfs4_file *fp, stateid_t *stid) | |||
2255 | return NULL; | 2321 | return NULL; |
2256 | } | 2322 | } |
2257 | 2323 | ||
2324 | int share_access_to_flags(u32 share_access) | ||
2325 | { | ||
2326 | share_access &= ~NFS4_SHARE_WANT_MASK; | ||
2327 | |||
2328 | return share_access == NFS4_SHARE_ACCESS_READ ? RD_STATE : WR_STATE; | ||
2329 | } | ||
2330 | |||
2258 | static __be32 | 2331 | static __be32 |
2259 | nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open, | 2332 | nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open, |
2260 | struct nfs4_delegation **dp) | 2333 | struct nfs4_delegation **dp) |
@@ -2265,8 +2338,7 @@ nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open, | |||
2265 | *dp = find_delegation_file(fp, &open->op_delegate_stateid); | 2338 | *dp = find_delegation_file(fp, &open->op_delegate_stateid); |
2266 | if (*dp == NULL) | 2339 | if (*dp == NULL) |
2267 | goto out; | 2340 | goto out; |
2268 | flags = open->op_share_access == NFS4_SHARE_ACCESS_READ ? | 2341 | flags = share_access_to_flags(open->op_share_access); |
2269 | RD_STATE : WR_STATE; | ||
2270 | status = nfs4_check_delegmode(*dp, flags); | 2342 | status = nfs4_check_delegmode(*dp, flags); |
2271 | if (status) | 2343 | if (status) |
2272 | *dp = NULL; | 2344 | *dp = NULL; |
@@ -2308,30 +2380,53 @@ nfs4_alloc_stateid(void) | |||
2308 | return kmem_cache_alloc(stateid_slab, GFP_KERNEL); | 2380 | return kmem_cache_alloc(stateid_slab, GFP_KERNEL); |
2309 | } | 2381 | } |
2310 | 2382 | ||
2383 | static inline int nfs4_access_to_access(u32 nfs4_access) | ||
2384 | { | ||
2385 | int flags = 0; | ||
2386 | |||
2387 | if (nfs4_access & NFS4_SHARE_ACCESS_READ) | ||
2388 | flags |= NFSD_MAY_READ; | ||
2389 | if (nfs4_access & NFS4_SHARE_ACCESS_WRITE) | ||
2390 | flags |= NFSD_MAY_WRITE; | ||
2391 | return flags; | ||
2392 | } | ||
2393 | |||
2394 | static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file | ||
2395 | *fp, struct svc_fh *cur_fh, u32 nfs4_access) | ||
2396 | { | ||
2397 | __be32 status; | ||
2398 | int oflag = nfs4_access_to_omode(nfs4_access); | ||
2399 | int access = nfs4_access_to_access(nfs4_access); | ||
2400 | |||
2401 | if (!fp->fi_fds[oflag]) { | ||
2402 | status = nfsd_open(rqstp, cur_fh, S_IFREG, access, | ||
2403 | &fp->fi_fds[oflag]); | ||
2404 | if (status == nfserr_dropit) | ||
2405 | status = nfserr_jukebox; | ||
2406 | if (status) | ||
2407 | return status; | ||
2408 | } | ||
2409 | nfs4_file_get_access(fp, oflag); | ||
2410 | |||
2411 | return nfs_ok; | ||
2412 | } | ||
2413 | |||
2311 | static __be32 | 2414 | static __be32 |
2312 | nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp, | 2415 | nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp, |
2313 | struct nfs4_delegation *dp, | 2416 | struct nfs4_file *fp, struct svc_fh *cur_fh, |
2314 | struct svc_fh *cur_fh, int flags) | 2417 | struct nfsd4_open *open) |
2315 | { | 2418 | { |
2316 | struct nfs4_stateid *stp; | 2419 | struct nfs4_stateid *stp; |
2420 | __be32 status; | ||
2317 | 2421 | ||
2318 | stp = nfs4_alloc_stateid(); | 2422 | stp = nfs4_alloc_stateid(); |
2319 | if (stp == NULL) | 2423 | if (stp == NULL) |
2320 | return nfserr_resource; | 2424 | return nfserr_resource; |
2321 | 2425 | ||
2322 | if (dp) { | 2426 | status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open->op_share_access); |
2323 | get_file(dp->dl_vfs_file); | 2427 | if (status) { |
2324 | stp->st_vfs_file = dp->dl_vfs_file; | 2428 | kmem_cache_free(stateid_slab, stp); |
2325 | } else { | 2429 | return status; |
2326 | __be32 status; | ||
2327 | status = nfsd_open(rqstp, cur_fh, S_IFREG, flags, | ||
2328 | &stp->st_vfs_file); | ||
2329 | if (status) { | ||
2330 | if (status == nfserr_dropit) | ||
2331 | status = nfserr_jukebox; | ||
2332 | kmem_cache_free(stateid_slab, stp); | ||
2333 | return status; | ||
2334 | } | ||
2335 | } | 2430 | } |
2336 | *stpp = stp; | 2431 | *stpp = stp; |
2337 | return 0; | 2432 | return 0; |
@@ -2353,35 +2448,30 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh, | |||
2353 | } | 2448 | } |
2354 | 2449 | ||
2355 | static __be32 | 2450 | static __be32 |
2356 | nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open) | 2451 | nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *cur_fh, struct nfs4_stateid *stp, struct nfsd4_open *open) |
2357 | { | 2452 | { |
2358 | struct file *filp = stp->st_vfs_file; | 2453 | u32 op_share_access, new_access; |
2359 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
2360 | unsigned int share_access, new_writer; | ||
2361 | __be32 status; | 2454 | __be32 status; |
2362 | 2455 | ||
2363 | set_access(&share_access, stp->st_access_bmap); | 2456 | set_access(&new_access, stp->st_access_bmap); |
2364 | new_writer = (~share_access) & open->op_share_access | 2457 | new_access = (~new_access) & open->op_share_access & ~NFS4_SHARE_WANT_MASK; |
2365 | & NFS4_SHARE_ACCESS_WRITE; | 2458 | |
2366 | 2459 | if (new_access) { | |
2367 | if (new_writer) { | 2460 | status = nfs4_get_vfs_file(rqstp, fp, cur_fh, new_access); |
2368 | int err = get_write_access(inode); | 2461 | if (status) |
2369 | if (err) | 2462 | return status; |
2370 | return nfserrno(err); | ||
2371 | err = mnt_want_write(cur_fh->fh_export->ex_path.mnt); | ||
2372 | if (err) | ||
2373 | return nfserrno(err); | ||
2374 | file_take_write(filp); | ||
2375 | } | 2463 | } |
2376 | status = nfsd4_truncate(rqstp, cur_fh, open); | 2464 | status = nfsd4_truncate(rqstp, cur_fh, open); |
2377 | if (status) { | 2465 | if (status) { |
2378 | if (new_writer) | 2466 | if (new_access) { |
2379 | put_write_access(inode); | 2467 | int oflag = nfs4_access_to_omode(new_access); |
2468 | nfs4_file_put_access(fp, oflag); | ||
2469 | } | ||
2380 | return status; | 2470 | return status; |
2381 | } | 2471 | } |
2382 | /* remember the open */ | 2472 | /* remember the open */ |
2383 | filp->f_mode |= open->op_share_access; | 2473 | op_share_access = open->op_share_access & ~NFS4_SHARE_WANT_MASK; |
2384 | __set_bit(open->op_share_access, &stp->st_access_bmap); | 2474 | __set_bit(op_share_access, &stp->st_access_bmap); |
2385 | __set_bit(open->op_share_deny, &stp->st_deny_bmap); | 2475 | __set_bit(open->op_share_deny, &stp->st_deny_bmap); |
2386 | 2476 | ||
2387 | return nfs_ok; | 2477 | return nfs_ok; |
@@ -2444,13 +2534,14 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta | |||
2444 | fl.fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK; | 2534 | fl.fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK; |
2445 | fl.fl_end = OFFSET_MAX; | 2535 | fl.fl_end = OFFSET_MAX; |
2446 | fl.fl_owner = (fl_owner_t)dp; | 2536 | fl.fl_owner = (fl_owner_t)dp; |
2447 | fl.fl_file = stp->st_vfs_file; | 2537 | fl.fl_file = find_readable_file(stp->st_file); |
2538 | BUG_ON(!fl.fl_file); | ||
2448 | fl.fl_pid = current->tgid; | 2539 | fl.fl_pid = current->tgid; |
2449 | 2540 | ||
2450 | /* vfs_setlease checks to see if delegation should be handed out. | 2541 | /* vfs_setlease checks to see if delegation should be handed out. |
2451 | * the lock_manager callbacks fl_mylease and fl_change are used | 2542 | * the lock_manager callbacks fl_mylease and fl_change are used |
2452 | */ | 2543 | */ |
2453 | if ((status = vfs_setlease(stp->st_vfs_file, fl.fl_type, &flp))) { | 2544 | if ((status = vfs_setlease(fl.fl_file, fl.fl_type, &flp))) { |
2454 | dprintk("NFSD: setlease failed [%d], no delegation\n", status); | 2545 | dprintk("NFSD: setlease failed [%d], no delegation\n", status); |
2455 | unhash_delegation(dp); | 2546 | unhash_delegation(dp); |
2456 | flag = NFS4_OPEN_DELEGATE_NONE; | 2547 | flag = NFS4_OPEN_DELEGATE_NONE; |
@@ -2514,18 +2605,12 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
2514 | */ | 2605 | */ |
2515 | if (stp) { | 2606 | if (stp) { |
2516 | /* Stateid was found, this is an OPEN upgrade */ | 2607 | /* Stateid was found, this is an OPEN upgrade */ |
2517 | status = nfs4_upgrade_open(rqstp, current_fh, stp, open); | 2608 | status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open); |
2518 | if (status) | 2609 | if (status) |
2519 | goto out; | 2610 | goto out; |
2520 | update_stateid(&stp->st_stateid); | 2611 | update_stateid(&stp->st_stateid); |
2521 | } else { | 2612 | } else { |
2522 | /* Stateid was not found, this is a new OPEN */ | 2613 | status = nfs4_new_open(rqstp, &stp, fp, current_fh, open); |
2523 | int flags = 0; | ||
2524 | if (open->op_share_access & NFS4_SHARE_ACCESS_READ) | ||
2525 | flags |= NFSD_MAY_READ; | ||
2526 | if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) | ||
2527 | flags |= NFSD_MAY_WRITE; | ||
2528 | status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags); | ||
2529 | if (status) | 2614 | if (status) |
2530 | goto out; | 2615 | goto out; |
2531 | init_stateid(stp, fp, open); | 2616 | init_stateid(stp, fp, open); |
@@ -2727,7 +2812,7 @@ search_close_lru(u32 st_id, int flags) | |||
2727 | static inline int | 2812 | static inline int |
2728 | nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp) | 2813 | nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp) |
2729 | { | 2814 | { |
2730 | return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_path.dentry->d_inode; | 2815 | return fhp->fh_dentry->d_inode != stp->st_file->fi_inode; |
2731 | } | 2816 | } |
2732 | 2817 | ||
2733 | static int | 2818 | static int |
@@ -2760,6 +2845,9 @@ __be32 nfs4_check_openmode(struct nfs4_stateid *stp, int flags) | |||
2760 | { | 2845 | { |
2761 | __be32 status = nfserr_openmode; | 2846 | __be32 status = nfserr_openmode; |
2762 | 2847 | ||
2848 | /* For lock stateid's, we test the parent open, not the lock: */ | ||
2849 | if (stp->st_openstp) | ||
2850 | stp = stp->st_openstp; | ||
2763 | if ((flags & WR_STATE) && (!access_permit_write(stp->st_access_bmap))) | 2851 | if ((flags & WR_STATE) && (!access_permit_write(stp->st_access_bmap))) |
2764 | goto out; | 2852 | goto out; |
2765 | if ((flags & RD_STATE) && (!access_permit_read(stp->st_access_bmap))) | 2853 | if ((flags & RD_STATE) && (!access_permit_read(stp->st_access_bmap))) |
@@ -2872,7 +2960,8 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | |||
2872 | goto out; | 2960 | goto out; |
2873 | renew_client(dp->dl_client); | 2961 | renew_client(dp->dl_client); |
2874 | if (filpp) | 2962 | if (filpp) |
2875 | *filpp = dp->dl_vfs_file; | 2963 | *filpp = find_readable_file(dp->dl_file); |
2964 | BUG_ON(!*filpp); | ||
2876 | } else { /* open or lock stateid */ | 2965 | } else { /* open or lock stateid */ |
2877 | stp = find_stateid(stateid, flags); | 2966 | stp = find_stateid(stateid, flags); |
2878 | if (!stp) | 2967 | if (!stp) |
@@ -2889,8 +2978,13 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | |||
2889 | if (status) | 2978 | if (status) |
2890 | goto out; | 2979 | goto out; |
2891 | renew_client(stp->st_stateowner->so_client); | 2980 | renew_client(stp->st_stateowner->so_client); |
2892 | if (filpp) | 2981 | if (filpp) { |
2893 | *filpp = stp->st_vfs_file; | 2982 | if (flags & RD_STATE) |
2983 | *filpp = find_readable_file(stp->st_file); | ||
2984 | else | ||
2985 | *filpp = find_writeable_file(stp->st_file); | ||
2986 | BUG_ON(!*filpp); /* assured by check_openmode */ | ||
2987 | } | ||
2894 | } | 2988 | } |
2895 | status = nfs_ok; | 2989 | status = nfs_ok; |
2896 | out: | 2990 | out: |
@@ -3126,8 +3220,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, | |||
3126 | goto out; | 3220 | goto out; |
3127 | } | 3221 | } |
3128 | set_access(&share_access, stp->st_access_bmap); | 3222 | set_access(&share_access, stp->st_access_bmap); |
3129 | nfs4_file_downgrade(stp->st_vfs_file, | 3223 | nfs4_file_downgrade(stp->st_file, share_access & ~od->od_share_access); |
3130 | share_access & ~od->od_share_access); | ||
3131 | 3224 | ||
3132 | reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap); | 3225 | reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap); |
3133 | reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap); | 3226 | reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap); |
@@ -3346,11 +3439,9 @@ static inline void | |||
3346 | nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny) | 3439 | nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny) |
3347 | { | 3440 | { |
3348 | struct nfs4_stateowner *sop; | 3441 | struct nfs4_stateowner *sop; |
3349 | unsigned int hval; | ||
3350 | 3442 | ||
3351 | if (fl->fl_lmops == &nfsd_posix_mng_ops) { | 3443 | if (fl->fl_lmops == &nfsd_posix_mng_ops) { |
3352 | sop = (struct nfs4_stateowner *) fl->fl_owner; | 3444 | sop = (struct nfs4_stateowner *) fl->fl_owner; |
3353 | hval = lockownerid_hashval(sop->so_id); | ||
3354 | kref_get(&sop->so_ref); | 3445 | kref_get(&sop->so_ref); |
3355 | deny->ld_sop = sop; | 3446 | deny->ld_sop = sop; |
3356 | deny->ld_clientid = sop->so_client->cl_clientid; | 3447 | deny->ld_clientid = sop->so_client->cl_clientid; |
@@ -3446,8 +3537,6 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc | |||
3446 | stp->st_stateid.si_stateownerid = sop->so_id; | 3537 | stp->st_stateid.si_stateownerid = sop->so_id; |
3447 | stp->st_stateid.si_fileid = fp->fi_id; | 3538 | stp->st_stateid.si_fileid = fp->fi_id; |
3448 | stp->st_stateid.si_generation = 0; | 3539 | stp->st_stateid.si_generation = 0; |
3449 | stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */ | ||
3450 | stp->st_access_bmap = open_stp->st_access_bmap; | ||
3451 | stp->st_deny_bmap = open_stp->st_deny_bmap; | 3540 | stp->st_deny_bmap = open_stp->st_deny_bmap; |
3452 | stp->st_openstp = open_stp; | 3541 | stp->st_openstp = open_stp; |
3453 | 3542 | ||
@@ -3547,7 +3636,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3547 | lock_sop = lock->lk_replay_owner; | 3636 | lock_sop = lock->lk_replay_owner; |
3548 | } | 3637 | } |
3549 | /* lock->lk_replay_owner and lock_stp have been created or found */ | 3638 | /* lock->lk_replay_owner and lock_stp have been created or found */ |
3550 | filp = lock_stp->st_vfs_file; | ||
3551 | 3639 | ||
3552 | status = nfserr_grace; | 3640 | status = nfserr_grace; |
3553 | if (locks_in_grace() && !lock->lk_reclaim) | 3641 | if (locks_in_grace() && !lock->lk_reclaim) |
@@ -3560,11 +3648,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3560 | switch (lock->lk_type) { | 3648 | switch (lock->lk_type) { |
3561 | case NFS4_READ_LT: | 3649 | case NFS4_READ_LT: |
3562 | case NFS4_READW_LT: | 3650 | case NFS4_READW_LT: |
3651 | filp = find_readable_file(lock_stp->st_file); | ||
3563 | file_lock.fl_type = F_RDLCK; | 3652 | file_lock.fl_type = F_RDLCK; |
3564 | cmd = F_SETLK; | 3653 | cmd = F_SETLK; |
3565 | break; | 3654 | break; |
3566 | case NFS4_WRITE_LT: | 3655 | case NFS4_WRITE_LT: |
3567 | case NFS4_WRITEW_LT: | 3656 | case NFS4_WRITEW_LT: |
3657 | filp = find_writeable_file(lock_stp->st_file); | ||
3568 | file_lock.fl_type = F_WRLCK; | 3658 | file_lock.fl_type = F_WRLCK; |
3569 | cmd = F_SETLK; | 3659 | cmd = F_SETLK; |
3570 | break; | 3660 | break; |
@@ -3572,6 +3662,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3572 | status = nfserr_inval; | 3662 | status = nfserr_inval; |
3573 | goto out; | 3663 | goto out; |
3574 | } | 3664 | } |
3665 | if (!filp) { | ||
3666 | status = nfserr_openmode; | ||
3667 | goto out; | ||
3668 | } | ||
3575 | file_lock.fl_owner = (fl_owner_t)lock_sop; | 3669 | file_lock.fl_owner = (fl_owner_t)lock_sop; |
3576 | file_lock.fl_pid = current->tgid; | 3670 | file_lock.fl_pid = current->tgid; |
3577 | file_lock.fl_file = filp; | 3671 | file_lock.fl_file = filp; |
@@ -3740,7 +3834,11 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
3740 | &locku->lu_stateowner, &stp, NULL))) | 3834 | &locku->lu_stateowner, &stp, NULL))) |
3741 | goto out; | 3835 | goto out; |
3742 | 3836 | ||
3743 | filp = stp->st_vfs_file; | 3837 | filp = find_any_file(stp->st_file); |
3838 | if (!filp) { | ||
3839 | status = nfserr_lock_range; | ||
3840 | goto out; | ||
3841 | } | ||
3744 | BUG_ON(!filp); | 3842 | BUG_ON(!filp); |
3745 | locks_init_lock(&file_lock); | 3843 | locks_init_lock(&file_lock); |
3746 | file_lock.fl_type = F_UNLCK; | 3844 | file_lock.fl_type = F_UNLCK; |
@@ -3787,10 +3885,10 @@ out_nfserr: | |||
3787 | * 0: no locks held by lockowner | 3885 | * 0: no locks held by lockowner |
3788 | */ | 3886 | */ |
3789 | static int | 3887 | static int |
3790 | check_for_locks(struct file *filp, struct nfs4_stateowner *lowner) | 3888 | check_for_locks(struct nfs4_file *filp, struct nfs4_stateowner *lowner) |
3791 | { | 3889 | { |
3792 | struct file_lock **flpp; | 3890 | struct file_lock **flpp; |
3793 | struct inode *inode = filp->f_path.dentry->d_inode; | 3891 | struct inode *inode = filp->fi_inode; |
3794 | int status = 0; | 3892 | int status = 0; |
3795 | 3893 | ||
3796 | lock_kernel(); | 3894 | lock_kernel(); |
@@ -3841,7 +3939,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, | |||
3841 | continue; | 3939 | continue; |
3842 | list_for_each_entry(stp, &sop->so_stateids, | 3940 | list_for_each_entry(stp, &sop->so_stateids, |
3843 | st_perstateowner) { | 3941 | st_perstateowner) { |
3844 | if (check_for_locks(stp->st_vfs_file, sop)) | 3942 | if (check_for_locks(stp->st_file, sop)) |
3845 | goto out; | 3943 | goto out; |
3846 | /* Note: so_perclient unused for lockowners, | 3944 | /* Note: so_perclient unused for lockowners, |
3847 | * so it's OK to fool with here. */ | 3945 | * so it's OK to fool with here. */ |
@@ -4066,16 +4164,8 @@ out_free_laundry: | |||
4066 | int | 4164 | int |
4067 | nfs4_state_start(void) | 4165 | nfs4_state_start(void) |
4068 | { | 4166 | { |
4069 | int ret; | ||
4070 | |||
4071 | if (nfs4_init) | ||
4072 | return 0; | ||
4073 | nfsd4_load_reboot_recovery_data(); | 4167 | nfsd4_load_reboot_recovery_data(); |
4074 | ret = __nfs4_state_start(); | 4168 | return __nfs4_state_start(); |
4075 | if (ret) | ||
4076 | return ret; | ||
4077 | nfs4_init = 1; | ||
4078 | return 0; | ||
4079 | } | 4169 | } |
4080 | 4170 | ||
4081 | static void | 4171 | static void |
@@ -4110,7 +4200,6 @@ __nfs4_state_shutdown(void) | |||
4110 | } | 4200 | } |
4111 | 4201 | ||
4112 | nfsd4_shutdown_recdir(); | 4202 | nfsd4_shutdown_recdir(); |
4113 | nfs4_init = 0; | ||
4114 | } | 4203 | } |
4115 | 4204 | ||
4116 | void | 4205 | void |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index ac17a7080239..f8931acb05f3 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -2630,7 +2630,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, | |||
2630 | } | 2630 | } |
2631 | read->rd_vlen = v; | 2631 | read->rd_vlen = v; |
2632 | 2632 | ||
2633 | nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp, | 2633 | nfserr = nfsd_read_file(read->rd_rqstp, read->rd_fhp, read->rd_filp, |
2634 | read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen, | 2634 | read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen, |
2635 | &maxcount); | 2635 | &maxcount); |
2636 | 2636 | ||
@@ -3325,6 +3325,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo | |||
3325 | } | 3325 | } |
3326 | /* Renew the clientid on success and on replay */ | 3326 | /* Renew the clientid on success and on replay */ |
3327 | release_session_client(cs->session); | 3327 | release_session_client(cs->session); |
3328 | nfsd4_put_session(cs->session); | ||
3328 | } | 3329 | } |
3329 | return 1; | 3330 | return 1; |
3330 | } | 3331 | } |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 508941c23af7..b53b1d042f1f 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -949,15 +949,12 @@ static ssize_t __write_ports_addfd(char *buf) | |||
949 | if (err != 0) | 949 | if (err != 0) |
950 | return err; | 950 | return err; |
951 | 951 | ||
952 | err = lockd_up(); | ||
953 | if (err != 0) | ||
954 | goto out; | ||
955 | |||
956 | err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); | 952 | err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); |
957 | if (err < 0) | 953 | if (err < 0) { |
958 | lockd_down(); | 954 | svc_destroy(nfsd_serv); |
955 | return err; | ||
956 | } | ||
959 | 957 | ||
960 | out: | ||
961 | /* Decrease the count, but don't shut down the service */ | 958 | /* Decrease the count, but don't shut down the service */ |
962 | nfsd_serv->sv_nrthreads--; | 959 | nfsd_serv->sv_nrthreads--; |
963 | return err; | 960 | return err; |
@@ -978,9 +975,6 @@ static ssize_t __write_ports_delfd(char *buf) | |||
978 | if (nfsd_serv != NULL) | 975 | if (nfsd_serv != NULL) |
979 | len = svc_sock_names(nfsd_serv, buf, | 976 | len = svc_sock_names(nfsd_serv, buf, |
980 | SIMPLE_TRANSACTION_LIMIT, toclose); | 977 | SIMPLE_TRANSACTION_LIMIT, toclose); |
981 | if (len >= 0) | ||
982 | lockd_down(); | ||
983 | |||
984 | kfree(toclose); | 978 | kfree(toclose); |
985 | return len; | 979 | return len; |
986 | } | 980 | } |
@@ -1014,6 +1008,9 @@ static ssize_t __write_ports_addxprt(char *buf) | |||
1014 | PF_INET6, port, SVC_SOCK_ANONYMOUS); | 1008 | PF_INET6, port, SVC_SOCK_ANONYMOUS); |
1015 | if (err < 0 && err != -EAFNOSUPPORT) | 1009 | if (err < 0 && err != -EAFNOSUPPORT) |
1016 | goto out_close; | 1010 | goto out_close; |
1011 | |||
1012 | /* Decrease the count, but don't shut down the service */ | ||
1013 | nfsd_serv->sv_nrthreads--; | ||
1017 | return 0; | 1014 | return 0; |
1018 | out_close: | 1015 | out_close: |
1019 | xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port); | 1016 | xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port); |
@@ -1022,8 +1019,7 @@ out_close: | |||
1022 | svc_xprt_put(xprt); | 1019 | svc_xprt_put(xprt); |
1023 | } | 1020 | } |
1024 | out_err: | 1021 | out_err: |
1025 | /* Decrease the count, but don't shut down the service */ | 1022 | svc_destroy(nfsd_serv); |
1026 | nfsd_serv->sv_nrthreads--; | ||
1027 | return err; | 1023 | return err; |
1028 | } | 1024 | } |
1029 | 1025 | ||
@@ -1194,7 +1190,7 @@ static ssize_t write_maxblksize(struct file *file, char *buf, size_t size) | |||
1194 | bsize = NFSSVC_MAXBLKSIZE; | 1190 | bsize = NFSSVC_MAXBLKSIZE; |
1195 | bsize &= ~(1024-1); | 1191 | bsize &= ~(1024-1); |
1196 | mutex_lock(&nfsd_mutex); | 1192 | mutex_lock(&nfsd_mutex); |
1197 | if (nfsd_serv && nfsd_serv->sv_nrthreads) { | 1193 | if (nfsd_serv) { |
1198 | mutex_unlock(&nfsd_mutex); | 1194 | mutex_unlock(&nfsd_mutex); |
1199 | return -EBUSY; | 1195 | return -EBUSY; |
1200 | } | 1196 | } |
@@ -1310,6 +1306,8 @@ static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) | |||
1310 | return -EINVAL; | 1306 | return -EINVAL; |
1311 | 1307 | ||
1312 | status = nfs4_reset_recoverydir(recdir); | 1308 | status = nfs4_reset_recoverydir(recdir); |
1309 | if (status) | ||
1310 | return status; | ||
1313 | } | 1311 | } |
1314 | 1312 | ||
1315 | return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n", | 1313 | return scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, "%s\n", |
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 72377761270e..b76ac3a82e39 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h | |||
@@ -153,6 +153,7 @@ void nfsd_lockd_shutdown(void); | |||
153 | #define nfserr_bad_seqid cpu_to_be32(NFSERR_BAD_SEQID) | 153 | #define nfserr_bad_seqid cpu_to_be32(NFSERR_BAD_SEQID) |
154 | #define nfserr_symlink cpu_to_be32(NFSERR_SYMLINK) | 154 | #define nfserr_symlink cpu_to_be32(NFSERR_SYMLINK) |
155 | #define nfserr_not_same cpu_to_be32(NFSERR_NOT_SAME) | 155 | #define nfserr_not_same cpu_to_be32(NFSERR_NOT_SAME) |
156 | #define nfserr_lock_range cpu_to_be32(NFSERR_LOCK_RANGE) | ||
156 | #define nfserr_restorefh cpu_to_be32(NFSERR_RESTOREFH) | 157 | #define nfserr_restorefh cpu_to_be32(NFSERR_RESTOREFH) |
157 | #define nfserr_attrnotsupp cpu_to_be32(NFSERR_ATTRNOTSUPP) | 158 | #define nfserr_attrnotsupp cpu_to_be32(NFSERR_ATTRNOTSUPP) |
158 | #define nfserr_bad_xdr cpu_to_be32(NFSERR_BAD_XDR) | 159 | #define nfserr_bad_xdr cpu_to_be32(NFSERR_BAD_XDR) |
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index a047ad6111ef..08e17264784b 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c | |||
@@ -144,7 +144,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp, | |||
144 | svc_reserve_auth(rqstp, (19<<2) + argp->count + 4); | 144 | svc_reserve_auth(rqstp, (19<<2) + argp->count + 4); |
145 | 145 | ||
146 | resp->count = argp->count; | 146 | resp->count = argp->count; |
147 | nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), NULL, | 147 | nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), |
148 | argp->offset, | 148 | argp->offset, |
149 | rqstp->rq_vec, argp->vlen, | 149 | rqstp->rq_vec, argp->vlen, |
150 | &resp->count); | 150 | &resp->count); |
@@ -290,7 +290,6 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, | |||
290 | * gospel of sun micro | 290 | * gospel of sun micro |
291 | */ | 291 | */ |
292 | if (type != S_IFREG) { | 292 | if (type != S_IFREG) { |
293 | int is_borc = 0; | ||
294 | if (type != S_IFBLK && type != S_IFCHR) { | 293 | if (type != S_IFBLK && type != S_IFCHR) { |
295 | rdev = 0; | 294 | rdev = 0; |
296 | } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) { | 295 | } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) { |
@@ -298,7 +297,6 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp, | |||
298 | type = S_IFIFO; | 297 | type = S_IFIFO; |
299 | } else { | 298 | } else { |
300 | /* Okay, char or block special */ | 299 | /* Okay, char or block special */ |
301 | is_borc = 1; | ||
302 | if (!rdev) | 300 | if (!rdev) |
303 | rdev = wanted; | 301 | rdev = wanted; |
304 | } | 302 | } |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 06b2a26edfe0..e2c43464f237 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
@@ -180,15 +180,80 @@ int nfsd_nrthreads(void) | |||
180 | return rv; | 180 | return rv; |
181 | } | 181 | } |
182 | 182 | ||
183 | static int nfsd_init_socks(int port) | ||
184 | { | ||
185 | int error; | ||
186 | if (!list_empty(&nfsd_serv->sv_permsocks)) | ||
187 | return 0; | ||
188 | |||
189 | error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port, | ||
190 | SVC_SOCK_DEFAULTS); | ||
191 | if (error < 0) | ||
192 | return error; | ||
193 | |||
194 | error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port, | ||
195 | SVC_SOCK_DEFAULTS); | ||
196 | if (error < 0) | ||
197 | return error; | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static bool nfsd_up = false; | ||
203 | |||
204 | static int nfsd_startup(unsigned short port, int nrservs) | ||
205 | { | ||
206 | int ret; | ||
207 | |||
208 | if (nfsd_up) | ||
209 | return 0; | ||
210 | /* | ||
211 | * Readahead param cache - will no-op if it already exists. | ||
212 | * (Note therefore results will be suboptimal if number of | ||
213 | * threads is modified after nfsd start.) | ||
214 | */ | ||
215 | ret = nfsd_racache_init(2*nrservs); | ||
216 | if (ret) | ||
217 | return ret; | ||
218 | ret = nfsd_init_socks(port); | ||
219 | if (ret) | ||
220 | goto out_racache; | ||
221 | ret = lockd_up(); | ||
222 | if (ret) | ||
223 | goto out_racache; | ||
224 | ret = nfs4_state_start(); | ||
225 | if (ret) | ||
226 | goto out_lockd; | ||
227 | nfsd_up = true; | ||
228 | return 0; | ||
229 | out_lockd: | ||
230 | lockd_down(); | ||
231 | out_racache: | ||
232 | nfsd_racache_shutdown(); | ||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | static void nfsd_shutdown(void) | ||
237 | { | ||
238 | /* | ||
239 | * write_ports can create the server without actually starting | ||
240 | * any threads--if we get shut down before any threads are | ||
241 | * started, then nfsd_last_thread will be run before any of this | ||
242 | * other initialization has been done. | ||
243 | */ | ||
244 | if (!nfsd_up) | ||
245 | return; | ||
246 | nfs4_state_shutdown(); | ||
247 | lockd_down(); | ||
248 | nfsd_racache_shutdown(); | ||
249 | nfsd_up = false; | ||
250 | } | ||
251 | |||
183 | static void nfsd_last_thread(struct svc_serv *serv) | 252 | static void nfsd_last_thread(struct svc_serv *serv) |
184 | { | 253 | { |
185 | /* When last nfsd thread exits we need to do some clean-up */ | 254 | /* When last nfsd thread exits we need to do some clean-up */ |
186 | struct svc_xprt *xprt; | ||
187 | list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) | ||
188 | lockd_down(); | ||
189 | nfsd_serv = NULL; | 255 | nfsd_serv = NULL; |
190 | nfsd_racache_shutdown(); | 256 | nfsd_shutdown(); |
191 | nfs4_state_shutdown(); | ||
192 | 257 | ||
193 | printk(KERN_WARNING "nfsd: last server has exited, flushing export " | 258 | printk(KERN_WARNING "nfsd: last server has exited, flushing export " |
194 | "cache\n"); | 259 | "cache\n"); |
@@ -263,45 +328,18 @@ int nfsd_create_serv(void) | |||
263 | nfsd_max_blksize >= 8*1024*2) | 328 | nfsd_max_blksize >= 8*1024*2) |
264 | nfsd_max_blksize /= 2; | 329 | nfsd_max_blksize /= 2; |
265 | } | 330 | } |
331 | nfsd_reset_versions(); | ||
266 | 332 | ||
267 | nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, | 333 | nfsd_serv = svc_create_pooled(&nfsd_program, nfsd_max_blksize, |
268 | nfsd_last_thread, nfsd, THIS_MODULE); | 334 | nfsd_last_thread, nfsd, THIS_MODULE); |
269 | if (nfsd_serv == NULL) | 335 | if (nfsd_serv == NULL) |
270 | err = -ENOMEM; | 336 | return -ENOMEM; |
271 | else | ||
272 | set_max_drc(); | ||
273 | 337 | ||
338 | set_max_drc(); | ||
274 | do_gettimeofday(&nfssvc_boot); /* record boot time */ | 339 | do_gettimeofday(&nfssvc_boot); /* record boot time */ |
275 | return err; | 340 | return err; |
276 | } | 341 | } |
277 | 342 | ||
278 | static int nfsd_init_socks(int port) | ||
279 | { | ||
280 | int error; | ||
281 | if (!list_empty(&nfsd_serv->sv_permsocks)) | ||
282 | return 0; | ||
283 | |||
284 | error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port, | ||
285 | SVC_SOCK_DEFAULTS); | ||
286 | if (error < 0) | ||
287 | return error; | ||
288 | |||
289 | error = lockd_up(); | ||
290 | if (error < 0) | ||
291 | return error; | ||
292 | |||
293 | error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port, | ||
294 | SVC_SOCK_DEFAULTS); | ||
295 | if (error < 0) | ||
296 | return error; | ||
297 | |||
298 | error = lockd_up(); | ||
299 | if (error < 0) | ||
300 | return error; | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | int nfsd_nrpools(void) | 343 | int nfsd_nrpools(void) |
306 | { | 344 | { |
307 | if (nfsd_serv == NULL) | 345 | if (nfsd_serv == NULL) |
@@ -376,10 +414,16 @@ int nfsd_set_nrthreads(int n, int *nthreads) | |||
376 | return err; | 414 | return err; |
377 | } | 415 | } |
378 | 416 | ||
417 | /* | ||
418 | * Adjust the number of threads and return the new number of threads. | ||
419 | * This is also the function that starts the server if necessary, if | ||
420 | * this is the first time nrservs is nonzero. | ||
421 | */ | ||
379 | int | 422 | int |
380 | nfsd_svc(unsigned short port, int nrservs) | 423 | nfsd_svc(unsigned short port, int nrservs) |
381 | { | 424 | { |
382 | int error; | 425 | int error; |
426 | bool nfsd_up_before; | ||
383 | 427 | ||
384 | mutex_lock(&nfsd_mutex); | 428 | mutex_lock(&nfsd_mutex); |
385 | dprintk("nfsd: creating service\n"); | 429 | dprintk("nfsd: creating service\n"); |
@@ -391,34 +435,29 @@ nfsd_svc(unsigned short port, int nrservs) | |||
391 | if (nrservs == 0 && nfsd_serv == NULL) | 435 | if (nrservs == 0 && nfsd_serv == NULL) |
392 | goto out; | 436 | goto out; |
393 | 437 | ||
394 | /* Readahead param cache - will no-op if it already exists */ | 438 | error = nfsd_create_serv(); |
395 | error = nfsd_racache_init(2*nrservs); | ||
396 | if (error<0) | ||
397 | goto out; | ||
398 | error = nfs4_state_start(); | ||
399 | if (error) | 439 | if (error) |
400 | goto out; | 440 | goto out; |
401 | 441 | ||
402 | nfsd_reset_versions(); | 442 | nfsd_up_before = nfsd_up; |
403 | |||
404 | error = nfsd_create_serv(); | ||
405 | 443 | ||
444 | error = nfsd_startup(port, nrservs); | ||
406 | if (error) | 445 | if (error) |
407 | goto out; | 446 | goto out_destroy; |
408 | error = nfsd_init_socks(port); | ||
409 | if (error) | ||
410 | goto failure; | ||
411 | |||
412 | error = svc_set_num_threads(nfsd_serv, NULL, nrservs); | 447 | error = svc_set_num_threads(nfsd_serv, NULL, nrservs); |
413 | if (error == 0) | 448 | if (error) |
414 | /* We are holding a reference to nfsd_serv which | 449 | goto out_shutdown; |
415 | * we don't want to count in the return value, | 450 | /* We are holding a reference to nfsd_serv which |
416 | * so subtract 1 | 451 | * we don't want to count in the return value, |
417 | */ | 452 | * so subtract 1 |
418 | error = nfsd_serv->sv_nrthreads - 1; | 453 | */ |
419 | failure: | 454 | error = nfsd_serv->sv_nrthreads - 1; |
455 | out_shutdown: | ||
456 | if (error < 0 && !nfsd_up_before) | ||
457 | nfsd_shutdown(); | ||
458 | out_destroy: | ||
420 | svc_destroy(nfsd_serv); /* Release server */ | 459 | svc_destroy(nfsd_serv); /* Release server */ |
421 | out: | 460 | out: |
422 | mutex_unlock(&nfsd_mutex); | 461 | mutex_unlock(&nfsd_mutex); |
423 | return error; | 462 | return error; |
424 | } | 463 | } |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 006c84230c7c..7731a75971dd 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
@@ -88,7 +88,6 @@ struct nfs4_delegation { | |||
88 | struct nfs4_client *dl_client; | 88 | struct nfs4_client *dl_client; |
89 | struct nfs4_file *dl_file; | 89 | struct nfs4_file *dl_file; |
90 | struct file_lock *dl_flock; | 90 | struct file_lock *dl_flock; |
91 | struct file *dl_vfs_file; | ||
92 | u32 dl_type; | 91 | u32 dl_type; |
93 | time_t dl_time; | 92 | time_t dl_time; |
94 | /* For recall: */ | 93 | /* For recall: */ |
@@ -342,12 +341,50 @@ struct nfs4_file { | |||
342 | struct list_head fi_hash; /* hash by "struct inode *" */ | 341 | struct list_head fi_hash; /* hash by "struct inode *" */ |
343 | struct list_head fi_stateids; | 342 | struct list_head fi_stateids; |
344 | struct list_head fi_delegations; | 343 | struct list_head fi_delegations; |
344 | /* One each for O_RDONLY, O_WRONLY, O_RDWR: */ | ||
345 | struct file * fi_fds[3]; | ||
346 | /* One each for O_RDONLY, O_WRONLY: */ | ||
347 | atomic_t fi_access[2]; | ||
348 | /* | ||
349 | * Each open stateid contributes 1 to either fi_readers or | ||
350 | * fi_writers, or both, depending on the open mode. A | ||
351 | * delegation also takes an fi_readers reference. Lock | ||
352 | * stateid's take none. | ||
353 | */ | ||
354 | atomic_t fi_readers; | ||
355 | atomic_t fi_writers; | ||
345 | struct inode *fi_inode; | 356 | struct inode *fi_inode; |
346 | u32 fi_id; /* used with stateowner->so_id | 357 | u32 fi_id; /* used with stateowner->so_id |
347 | * for stateid_hashtbl hash */ | 358 | * for stateid_hashtbl hash */ |
348 | bool fi_had_conflict; | 359 | bool fi_had_conflict; |
349 | }; | 360 | }; |
350 | 361 | ||
362 | /* XXX: for first cut may fall back on returning file that doesn't work | ||
363 | * at all? */ | ||
364 | static inline struct file *find_writeable_file(struct nfs4_file *f) | ||
365 | { | ||
366 | if (f->fi_fds[O_RDWR]) | ||
367 | return f->fi_fds[O_RDWR]; | ||
368 | return f->fi_fds[O_WRONLY]; | ||
369 | } | ||
370 | |||
371 | static inline struct file *find_readable_file(struct nfs4_file *f) | ||
372 | { | ||
373 | if (f->fi_fds[O_RDWR]) | ||
374 | return f->fi_fds[O_RDWR]; | ||
375 | return f->fi_fds[O_RDONLY]; | ||
376 | } | ||
377 | |||
378 | static inline struct file *find_any_file(struct nfs4_file *f) | ||
379 | { | ||
380 | if (f->fi_fds[O_RDWR]) | ||
381 | return f->fi_fds[O_RDWR]; | ||
382 | else if (f->fi_fds[O_RDWR]) | ||
383 | return f->fi_fds[O_WRONLY]; | ||
384 | else | ||
385 | return f->fi_fds[O_RDONLY]; | ||
386 | } | ||
387 | |||
351 | /* | 388 | /* |
352 | * nfs4_stateid can either be an open stateid or (eventually) a lock stateid | 389 | * nfs4_stateid can either be an open stateid or (eventually) a lock stateid |
353 | * | 390 | * |
@@ -373,7 +410,6 @@ struct nfs4_stateid { | |||
373 | struct nfs4_stateowner * st_stateowner; | 410 | struct nfs4_stateowner * st_stateowner; |
374 | struct nfs4_file * st_file; | 411 | struct nfs4_file * st_file; |
375 | stateid_t st_stateid; | 412 | stateid_t st_stateid; |
376 | struct file * st_vfs_file; | ||
377 | unsigned long st_access_bmap; | 413 | unsigned long st_access_bmap; |
378 | unsigned long st_deny_bmap; | 414 | unsigned long st_deny_bmap; |
379 | struct nfs4_stateid * st_openstp; | 415 | struct nfs4_stateid * st_openstp; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 3c111120b619..9df85a13af28 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -604,7 +604,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac | |||
604 | return error; | 604 | return error; |
605 | } | 605 | } |
606 | 606 | ||
607 | #endif /* defined(CONFIG_NFS_V4) */ | 607 | #endif /* defined(CONFIG_NFSD_V4) */ |
608 | 608 | ||
609 | #ifdef CONFIG_NFSD_V3 | 609 | #ifdef CONFIG_NFSD_V3 |
610 | /* | 610 | /* |
@@ -903,7 +903,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
903 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) | 903 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) |
904 | { | 904 | { |
905 | struct inode *inode; | 905 | struct inode *inode; |
906 | struct raparms *ra; | ||
907 | mm_segment_t oldfs; | 906 | mm_segment_t oldfs; |
908 | __be32 err; | 907 | __be32 err; |
909 | int host_err; | 908 | int host_err; |
@@ -914,12 +913,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
914 | if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count)) | 913 | if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count)) |
915 | goto out; | 914 | goto out; |
916 | 915 | ||
917 | /* Get readahead parameters */ | ||
918 | ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino); | ||
919 | |||
920 | if (ra && ra->p_set) | ||
921 | file->f_ra = ra->p_ra; | ||
922 | |||
923 | if (file->f_op->splice_read && rqstp->rq_splice_ok) { | 916 | if (file->f_op->splice_read && rqstp->rq_splice_ok) { |
924 | struct splice_desc sd = { | 917 | struct splice_desc sd = { |
925 | .len = 0, | 918 | .len = 0, |
@@ -937,16 +930,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
937 | set_fs(oldfs); | 930 | set_fs(oldfs); |
938 | } | 931 | } |
939 | 932 | ||
940 | /* Write back readahead params */ | ||
941 | if (ra) { | ||
942 | struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex]; | ||
943 | spin_lock(&rab->pb_lock); | ||
944 | ra->p_ra = file->f_ra; | ||
945 | ra->p_set = 1; | ||
946 | ra->p_count--; | ||
947 | spin_unlock(&rab->pb_lock); | ||
948 | } | ||
949 | |||
950 | if (host_err >= 0) { | 933 | if (host_err >= 0) { |
951 | nfsdstats.io_read += host_err; | 934 | nfsdstats.io_read += host_err; |
952 | *count = host_err; | 935 | *count = host_err; |
@@ -1086,8 +1069,45 @@ out: | |||
1086 | * on entry. On return, *count contains the number of bytes actually read. | 1069 | * on entry. On return, *count contains the number of bytes actually read. |
1087 | * N.B. After this call fhp needs an fh_put | 1070 | * N.B. After this call fhp needs an fh_put |
1088 | */ | 1071 | */ |
1072 | __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, | ||
1073 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) | ||
1074 | { | ||
1075 | struct file *file; | ||
1076 | struct inode *inode; | ||
1077 | struct raparms *ra; | ||
1078 | __be32 err; | ||
1079 | |||
1080 | err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); | ||
1081 | if (err) | ||
1082 | return err; | ||
1083 | |||
1084 | inode = file->f_path.dentry->d_inode; | ||
1085 | |||
1086 | /* Get readahead parameters */ | ||
1087 | ra = nfsd_get_raparms(inode->i_sb->s_dev, inode->i_ino); | ||
1088 | |||
1089 | if (ra && ra->p_set) | ||
1090 | file->f_ra = ra->p_ra; | ||
1091 | |||
1092 | err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); | ||
1093 | |||
1094 | /* Write back readahead params */ | ||
1095 | if (ra) { | ||
1096 | struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex]; | ||
1097 | spin_lock(&rab->pb_lock); | ||
1098 | ra->p_ra = file->f_ra; | ||
1099 | ra->p_set = 1; | ||
1100 | ra->p_count--; | ||
1101 | spin_unlock(&rab->pb_lock); | ||
1102 | } | ||
1103 | |||
1104 | nfsd_close(file); | ||
1105 | return err; | ||
1106 | } | ||
1107 | |||
1108 | /* As above, but use the provided file descriptor. */ | ||
1089 | __be32 | 1109 | __be32 |
1090 | nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | 1110 | nfsd_read_file(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, |
1091 | loff_t offset, struct kvec *vec, int vlen, | 1111 | loff_t offset, struct kvec *vec, int vlen, |
1092 | unsigned long *count) | 1112 | unsigned long *count) |
1093 | { | 1113 | { |
@@ -1099,13 +1119,8 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
1099 | if (err) | 1119 | if (err) |
1100 | goto out; | 1120 | goto out; |
1101 | err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); | 1121 | err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); |
1102 | } else { | 1122 | } else /* Note file may still be NULL in NFSv4 special stateid case: */ |
1103 | err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file); | 1123 | err = nfsd_read(rqstp, fhp, offset, vec, vlen, count); |
1104 | if (err) | ||
1105 | goto out; | ||
1106 | err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count); | ||
1107 | nfsd_close(file); | ||
1108 | } | ||
1109 | out: | 1124 | out: |
1110 | return err; | 1125 | return err; |
1111 | } | 1126 | } |
@@ -1631,7 +1646,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1631 | char *name, int len, struct svc_fh *tfhp) | 1646 | char *name, int len, struct svc_fh *tfhp) |
1632 | { | 1647 | { |
1633 | struct dentry *ddir, *dnew, *dold; | 1648 | struct dentry *ddir, *dnew, *dold; |
1634 | struct inode *dirp, *dest; | 1649 | struct inode *dirp; |
1635 | __be32 err; | 1650 | __be32 err; |
1636 | int host_err; | 1651 | int host_err; |
1637 | 1652 | ||
@@ -1659,7 +1674,6 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1659 | goto out_nfserr; | 1674 | goto out_nfserr; |
1660 | 1675 | ||
1661 | dold = tfhp->fh_dentry; | 1676 | dold = tfhp->fh_dentry; |
1662 | dest = dold->d_inode; | ||
1663 | 1677 | ||
1664 | host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt); | 1678 | host_err = mnt_want_write(tfhp->fh_export->ex_path.mnt); |
1665 | if (host_err) { | 1679 | if (host_err) { |
@@ -2038,7 +2052,6 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, | |||
2038 | struct dentry *dentry, int acc) | 2052 | struct dentry *dentry, int acc) |
2039 | { | 2053 | { |
2040 | struct inode *inode = dentry->d_inode; | 2054 | struct inode *inode = dentry->d_inode; |
2041 | struct path path; | ||
2042 | int err; | 2055 | int err; |
2043 | 2056 | ||
2044 | if (acc == NFSD_MAY_NOP) | 2057 | if (acc == NFSD_MAY_NOP) |
@@ -2111,15 +2124,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, | |||
2111 | if (err == -EACCES && S_ISREG(inode->i_mode) && | 2124 | if (err == -EACCES && S_ISREG(inode->i_mode) && |
2112 | acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE)) | 2125 | acc == (NFSD_MAY_READ | NFSD_MAY_OWNER_OVERRIDE)) |
2113 | err = inode_permission(inode, MAY_EXEC); | 2126 | err = inode_permission(inode, MAY_EXEC); |
2114 | if (err) | ||
2115 | goto nfsd_out; | ||
2116 | 2127 | ||
2117 | /* Do integrity (permission) checking now, but defer incrementing | ||
2118 | * IMA counts to the actual file open. | ||
2119 | */ | ||
2120 | path.mnt = exp->ex_path.mnt; | ||
2121 | path.dentry = dentry; | ||
2122 | nfsd_out: | ||
2123 | return err? nfserrno(err) : 0; | 2128 | return err? nfserrno(err) : 0; |
2124 | } | 2129 | } |
2125 | 2130 | ||
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index 217a62c2a357..9a370a5e36b7 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h | |||
@@ -64,7 +64,9 @@ __be32 nfsd_commit(struct svc_rqst *, struct svc_fh *, | |||
64 | __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, int, | 64 | __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, int, |
65 | int, struct file **); | 65 | int, struct file **); |
66 | void nfsd_close(struct file *); | 66 | void nfsd_close(struct file *); |
67 | __be32 nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *, | 67 | __be32 nfsd_read(struct svc_rqst *, struct svc_fh *, |
68 | loff_t, struct kvec *, int, unsigned long *); | ||
69 | __be32 nfsd_read_file(struct svc_rqst *, struct svc_fh *, struct file *, | ||
68 | loff_t, struct kvec *, int, unsigned long *); | 70 | loff_t, struct kvec *, int, unsigned long *); |
69 | __be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *, | 71 | __be32 nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *, |
70 | loff_t, struct kvec *,int, unsigned long *, int *); | 72 | loff_t, struct kvec *,int, unsigned long *, int *); |
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index effdbdbe6c11..3dbdc1d356bf 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include "nilfs.h" | 26 | #include "nilfs.h" |
27 | #include "bmap.h" | 27 | #include "bmap.h" |
28 | #include "sb.h" | 28 | #include "sb.h" |
29 | #include "btree.h" | ||
30 | #include "direct.h" | ||
29 | #include "btnode.h" | 31 | #include "btnode.h" |
30 | #include "mdt.h" | 32 | #include "mdt.h" |
31 | #include "dat.h" | 33 | #include "dat.h" |
@@ -533,7 +535,7 @@ void nilfs_bmap_init_gc(struct nilfs_bmap *bmap) | |||
533 | 535 | ||
534 | void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) | 536 | void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) |
535 | { | 537 | { |
536 | memcpy(gcbmap, bmap, sizeof(union nilfs_bmap_union)); | 538 | memcpy(gcbmap, bmap, sizeof(*bmap)); |
537 | init_rwsem(&gcbmap->b_sem); | 539 | init_rwsem(&gcbmap->b_sem); |
538 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); | 540 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); |
539 | gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode; | 541 | gcbmap->b_inode = &NILFS_BMAP_I(gcbmap)->vfs_inode; |
@@ -541,7 +543,7 @@ void nilfs_bmap_init_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) | |||
541 | 543 | ||
542 | void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) | 544 | void nilfs_bmap_commit_gcdat(struct nilfs_bmap *gcbmap, struct nilfs_bmap *bmap) |
543 | { | 545 | { |
544 | memcpy(bmap, gcbmap, sizeof(union nilfs_bmap_union)); | 546 | memcpy(bmap, gcbmap, sizeof(*bmap)); |
545 | init_rwsem(&bmap->b_sem); | 547 | init_rwsem(&bmap->b_sem); |
546 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); | 548 | lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); |
547 | bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; | 549 | bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; |
diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h index 9980d7dbab91..a20569b19929 100644 --- a/fs/nilfs2/bmap.h +++ b/fs/nilfs2/bmap.h | |||
@@ -32,11 +32,6 @@ | |||
32 | 32 | ||
33 | #define NILFS_BMAP_INVALID_PTR 0 | 33 | #define NILFS_BMAP_INVALID_PTR 0 |
34 | 34 | ||
35 | #define nilfs_bmap_dkey_to_key(dkey) le64_to_cpu(dkey) | ||
36 | #define nilfs_bmap_key_to_dkey(key) cpu_to_le64(key) | ||
37 | #define nilfs_bmap_dptr_to_ptr(dptr) le64_to_cpu(dptr) | ||
38 | #define nilfs_bmap_ptr_to_dptr(ptr) cpu_to_le64(ptr) | ||
39 | |||
40 | #define nilfs_bmap_keydiff_abs(diff) ((diff) < 0 ? -(diff) : (diff)) | 35 | #define nilfs_bmap_keydiff_abs(diff) ((diff) < 0 ? -(diff) : (diff)) |
41 | 36 | ||
42 | 37 | ||
@@ -71,7 +66,7 @@ struct nilfs_bmap_operations { | |||
71 | int (*bop_delete)(struct nilfs_bmap *, __u64); | 66 | int (*bop_delete)(struct nilfs_bmap *, __u64); |
72 | void (*bop_clear)(struct nilfs_bmap *); | 67 | void (*bop_clear)(struct nilfs_bmap *); |
73 | 68 | ||
74 | int (*bop_propagate)(const struct nilfs_bmap *, struct buffer_head *); | 69 | int (*bop_propagate)(struct nilfs_bmap *, struct buffer_head *); |
75 | void (*bop_lookup_dirty_buffers)(struct nilfs_bmap *, | 70 | void (*bop_lookup_dirty_buffers)(struct nilfs_bmap *, |
76 | struct list_head *); | 71 | struct list_head *); |
77 | 72 | ||
@@ -110,6 +105,7 @@ static inline int nilfs_bmap_is_new_ptr(unsigned long ptr) | |||
110 | * @b_last_allocated_ptr: last allocated ptr for data block | 105 | * @b_last_allocated_ptr: last allocated ptr for data block |
111 | * @b_ptr_type: pointer type | 106 | * @b_ptr_type: pointer type |
112 | * @b_state: state | 107 | * @b_state: state |
108 | * @b_nchildren_per_block: maximum number of child nodes for non-root nodes | ||
113 | */ | 109 | */ |
114 | struct nilfs_bmap { | 110 | struct nilfs_bmap { |
115 | union { | 111 | union { |
@@ -123,6 +119,7 @@ struct nilfs_bmap { | |||
123 | __u64 b_last_allocated_ptr; | 119 | __u64 b_last_allocated_ptr; |
124 | int b_ptr_type; | 120 | int b_ptr_type; |
125 | int b_state; | 121 | int b_state; |
122 | __u16 b_nchildren_per_block; | ||
126 | }; | 123 | }; |
127 | 124 | ||
128 | /* pointer type */ | 125 | /* pointer type */ |
@@ -224,6 +221,13 @@ static inline void nilfs_bmap_abort_end_ptr(struct nilfs_bmap *bmap, | |||
224 | nilfs_dat_abort_end(dat, &req->bpr_req); | 221 | nilfs_dat_abort_end(dat, &req->bpr_req); |
225 | } | 222 | } |
226 | 223 | ||
224 | static inline void nilfs_bmap_set_target_v(struct nilfs_bmap *bmap, __u64 key, | ||
225 | __u64 ptr) | ||
226 | { | ||
227 | bmap->b_last_allocated_key = key; | ||
228 | bmap->b_last_allocated_ptr = ptr; | ||
229 | } | ||
230 | |||
227 | __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *, | 231 | __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *, |
228 | const struct buffer_head *); | 232 | const struct buffer_head *); |
229 | 233 | ||
diff --git a/fs/nilfs2/bmap_union.h b/fs/nilfs2/bmap_union.h deleted file mode 100644 index d41509bff47b..000000000000 --- a/fs/nilfs2/bmap_union.h +++ /dev/null | |||
@@ -1,42 +0,0 @@ | |||
1 | /* | ||
2 | * bmap_union.h - NILFS block mapping. | ||
3 | * | ||
4 | * Copyright (C) 2006-2008 Nippon Telegraph and Telephone Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | * | ||
20 | * Written by Koji Sato <koji@osrg.net>. | ||
21 | */ | ||
22 | |||
23 | #ifndef _NILFS_BMAP_UNION_H | ||
24 | #define _NILFS_BMAP_UNION_H | ||
25 | |||
26 | #include "bmap.h" | ||
27 | #include "direct.h" | ||
28 | #include "btree.h" | ||
29 | |||
30 | /** | ||
31 | * nilfs_bmap_union - | ||
32 | * @bi_bmap: bmap structure | ||
33 | * @bi_btree: direct map structure | ||
34 | * @bi_direct: B-tree structure | ||
35 | */ | ||
36 | union nilfs_bmap_union { | ||
37 | struct nilfs_bmap bi_bmap; | ||
38 | struct nilfs_direct bi_direct; | ||
39 | struct nilfs_btree bi_btree; | ||
40 | }; | ||
41 | |||
42 | #endif /* _NILFS_BMAP_UNION_H */ | ||
diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c index 447ce47a3306..f78ab1044d1d 100644 --- a/fs/nilfs2/btnode.c +++ b/fs/nilfs2/btnode.c | |||
@@ -96,10 +96,12 @@ nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr) | |||
96 | } | 96 | } |
97 | 97 | ||
98 | int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, | 98 | int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, |
99 | sector_t pblocknr, struct buffer_head **pbh) | 99 | sector_t pblocknr, int mode, |
100 | struct buffer_head **pbh, sector_t *submit_ptr) | ||
100 | { | 101 | { |
101 | struct buffer_head *bh; | 102 | struct buffer_head *bh; |
102 | struct inode *inode = NILFS_BTNC_I(btnc); | 103 | struct inode *inode = NILFS_BTNC_I(btnc); |
104 | struct page *page; | ||
103 | int err; | 105 | int err; |
104 | 106 | ||
105 | bh = nilfs_grab_buffer(inode, btnc, blocknr, 1 << BH_NILFS_Node); | 107 | bh = nilfs_grab_buffer(inode, btnc, blocknr, 1 << BH_NILFS_Node); |
@@ -107,6 +109,7 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, | |||
107 | return -ENOMEM; | 109 | return -ENOMEM; |
108 | 110 | ||
109 | err = -EEXIST; /* internal code */ | 111 | err = -EEXIST; /* internal code */ |
112 | page = bh->b_page; | ||
110 | 113 | ||
111 | if (buffer_uptodate(bh) || buffer_dirty(bh)) | 114 | if (buffer_uptodate(bh) || buffer_dirty(bh)) |
112 | goto found; | 115 | goto found; |
@@ -125,7 +128,16 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, | |||
125 | } | 128 | } |
126 | } | 129 | } |
127 | } | 130 | } |
128 | lock_buffer(bh); | 131 | |
132 | if (mode == READA) { | ||
133 | if (pblocknr != *submit_ptr + 1 || !trylock_buffer(bh)) { | ||
134 | err = -EBUSY; /* internal code */ | ||
135 | brelse(bh); | ||
136 | goto out_locked; | ||
137 | } | ||
138 | } else { /* mode == READ */ | ||
139 | lock_buffer(bh); | ||
140 | } | ||
129 | if (buffer_uptodate(bh)) { | 141 | if (buffer_uptodate(bh)) { |
130 | unlock_buffer(bh); | 142 | unlock_buffer(bh); |
131 | err = -EEXIST; /* internal code */ | 143 | err = -EEXIST; /* internal code */ |
@@ -136,15 +148,16 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, | |||
136 | bh->b_blocknr = pblocknr; /* set block address for read */ | 148 | bh->b_blocknr = pblocknr; /* set block address for read */ |
137 | bh->b_end_io = end_buffer_read_sync; | 149 | bh->b_end_io = end_buffer_read_sync; |
138 | get_bh(bh); | 150 | get_bh(bh); |
139 | submit_bh(READ, bh); | 151 | submit_bh(mode, bh); |
140 | bh->b_blocknr = blocknr; /* set back to the given block address */ | 152 | bh->b_blocknr = blocknr; /* set back to the given block address */ |
153 | *submit_ptr = pblocknr; | ||
141 | err = 0; | 154 | err = 0; |
142 | found: | 155 | found: |
143 | *pbh = bh; | 156 | *pbh = bh; |
144 | 157 | ||
145 | out_locked: | 158 | out_locked: |
146 | unlock_page(bh->b_page); | 159 | unlock_page(page); |
147 | page_cache_release(bh->b_page); | 160 | page_cache_release(page); |
148 | return err; | 161 | return err; |
149 | } | 162 | } |
150 | 163 | ||
diff --git a/fs/nilfs2/btnode.h b/fs/nilfs2/btnode.h index 07da83f07712..79037494f1e0 100644 --- a/fs/nilfs2/btnode.h +++ b/fs/nilfs2/btnode.h | |||
@@ -42,8 +42,8 @@ void nilfs_btnode_cache_init(struct address_space *, struct backing_dev_info *); | |||
42 | void nilfs_btnode_cache_clear(struct address_space *); | 42 | void nilfs_btnode_cache_clear(struct address_space *); |
43 | struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc, | 43 | struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc, |
44 | __u64 blocknr); | 44 | __u64 blocknr); |
45 | int nilfs_btnode_submit_block(struct address_space *, __u64, sector_t, | 45 | int nilfs_btnode_submit_block(struct address_space *, __u64, sector_t, int, |
46 | struct buffer_head **); | 46 | struct buffer_head **, sector_t *); |
47 | void nilfs_btnode_delete(struct buffer_head *); | 47 | void nilfs_btnode_delete(struct buffer_head *); |
48 | int nilfs_btnode_prepare_change_key(struct address_space *, | 48 | int nilfs_btnode_prepare_change_key(struct address_space *, |
49 | struct nilfs_btnode_chkey_ctxt *); | 49 | struct nilfs_btnode_chkey_ctxt *); |
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index b27a342c5af6..300c2bc00c3f 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c | |||
@@ -66,30 +66,10 @@ static void nilfs_btree_free_path(struct nilfs_btree_path *path) | |||
66 | /* | 66 | /* |
67 | * B-tree node operations | 67 | * B-tree node operations |
68 | */ | 68 | */ |
69 | static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr, | 69 | static int nilfs_btree_get_new_block(const struct nilfs_bmap *btree, |
70 | struct buffer_head **bhp) | ||
71 | { | ||
72 | struct address_space *btnc = | ||
73 | &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache; | ||
74 | int err; | ||
75 | |||
76 | err = nilfs_btnode_submit_block(btnc, ptr, 0, bhp); | ||
77 | if (err) | ||
78 | return err == -EEXIST ? 0 : err; | ||
79 | |||
80 | wait_on_buffer(*bhp); | ||
81 | if (!buffer_uptodate(*bhp)) { | ||
82 | brelse(*bhp); | ||
83 | return -EIO; | ||
84 | } | ||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | static int nilfs_btree_get_new_block(const struct nilfs_btree *btree, | ||
89 | __u64 ptr, struct buffer_head **bhp) | 70 | __u64 ptr, struct buffer_head **bhp) |
90 | { | 71 | { |
91 | struct address_space *btnc = | 72 | struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache; |
92 | &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache; | ||
93 | struct buffer_head *bh; | 73 | struct buffer_head *bh; |
94 | 74 | ||
95 | bh = nilfs_btnode_create_block(btnc, ptr); | 75 | bh = nilfs_btnode_create_block(btnc, ptr); |
@@ -101,71 +81,55 @@ static int nilfs_btree_get_new_block(const struct nilfs_btree *btree, | |||
101 | return 0; | 81 | return 0; |
102 | } | 82 | } |
103 | 83 | ||
104 | static inline int | 84 | static int nilfs_btree_node_get_flags(const struct nilfs_btree_node *node) |
105 | nilfs_btree_node_get_flags(const struct nilfs_btree_node *node) | ||
106 | { | 85 | { |
107 | return node->bn_flags; | 86 | return node->bn_flags; |
108 | } | 87 | } |
109 | 88 | ||
110 | static inline void | 89 | static void |
111 | nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags) | 90 | nilfs_btree_node_set_flags(struct nilfs_btree_node *node, int flags) |
112 | { | 91 | { |
113 | node->bn_flags = flags; | 92 | node->bn_flags = flags; |
114 | } | 93 | } |
115 | 94 | ||
116 | static inline int nilfs_btree_node_root(const struct nilfs_btree_node *node) | 95 | static int nilfs_btree_node_root(const struct nilfs_btree_node *node) |
117 | { | 96 | { |
118 | return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT; | 97 | return nilfs_btree_node_get_flags(node) & NILFS_BTREE_NODE_ROOT; |
119 | } | 98 | } |
120 | 99 | ||
121 | static inline int | 100 | static int nilfs_btree_node_get_level(const struct nilfs_btree_node *node) |
122 | nilfs_btree_node_get_level(const struct nilfs_btree_node *node) | ||
123 | { | 101 | { |
124 | return node->bn_level; | 102 | return node->bn_level; |
125 | } | 103 | } |
126 | 104 | ||
127 | static inline void | 105 | static void |
128 | nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level) | 106 | nilfs_btree_node_set_level(struct nilfs_btree_node *node, int level) |
129 | { | 107 | { |
130 | node->bn_level = level; | 108 | node->bn_level = level; |
131 | } | 109 | } |
132 | 110 | ||
133 | static inline int | 111 | static int nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node) |
134 | nilfs_btree_node_get_nchildren(const struct nilfs_btree_node *node) | ||
135 | { | 112 | { |
136 | return le16_to_cpu(node->bn_nchildren); | 113 | return le16_to_cpu(node->bn_nchildren); |
137 | } | 114 | } |
138 | 115 | ||
139 | static inline void | 116 | static void |
140 | nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren) | 117 | nilfs_btree_node_set_nchildren(struct nilfs_btree_node *node, int nchildren) |
141 | { | 118 | { |
142 | node->bn_nchildren = cpu_to_le16(nchildren); | 119 | node->bn_nchildren = cpu_to_le16(nchildren); |
143 | } | 120 | } |
144 | 121 | ||
145 | static inline int nilfs_btree_node_size(const struct nilfs_btree *btree) | 122 | static int nilfs_btree_node_size(const struct nilfs_bmap *btree) |
146 | { | 123 | { |
147 | return 1 << btree->bt_bmap.b_inode->i_blkbits; | 124 | return 1 << btree->b_inode->i_blkbits; |
148 | } | 125 | } |
149 | 126 | ||
150 | static inline int | 127 | static int nilfs_btree_nchildren_per_block(const struct nilfs_bmap *btree) |
151 | nilfs_btree_node_nchildren_min(const struct nilfs_btree_node *node, | ||
152 | const struct nilfs_btree *btree) | ||
153 | { | 128 | { |
154 | return nilfs_btree_node_root(node) ? | 129 | return btree->b_nchildren_per_block; |
155 | NILFS_BTREE_ROOT_NCHILDREN_MIN : | ||
156 | NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree)); | ||
157 | } | 130 | } |
158 | 131 | ||
159 | static inline int | 132 | static __le64 * |
160 | nilfs_btree_node_nchildren_max(const struct nilfs_btree_node *node, | ||
161 | const struct nilfs_btree *btree) | ||
162 | { | ||
163 | return nilfs_btree_node_root(node) ? | ||
164 | NILFS_BTREE_ROOT_NCHILDREN_MAX : | ||
165 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(btree)); | ||
166 | } | ||
167 | |||
168 | static inline __le64 * | ||
169 | nilfs_btree_node_dkeys(const struct nilfs_btree_node *node) | 133 | nilfs_btree_node_dkeys(const struct nilfs_btree_node *node) |
170 | { | 134 | { |
171 | return (__le64 *)((char *)(node + 1) + | 135 | return (__le64 *)((char *)(node + 1) + |
@@ -173,45 +137,40 @@ nilfs_btree_node_dkeys(const struct nilfs_btree_node *node) | |||
173 | 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE)); | 137 | 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE)); |
174 | } | 138 | } |
175 | 139 | ||
176 | static inline __le64 * | 140 | static __le64 * |
177 | nilfs_btree_node_dptrs(const struct nilfs_btree_node *node, | 141 | nilfs_btree_node_dptrs(const struct nilfs_btree_node *node, int ncmax) |
178 | const struct nilfs_btree *btree) | ||
179 | { | 142 | { |
180 | return (__le64 *)(nilfs_btree_node_dkeys(node) + | 143 | return (__le64 *)(nilfs_btree_node_dkeys(node) + ncmax); |
181 | nilfs_btree_node_nchildren_max(node, btree)); | ||
182 | } | 144 | } |
183 | 145 | ||
184 | static inline __u64 | 146 | static __u64 |
185 | nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index) | 147 | nilfs_btree_node_get_key(const struct nilfs_btree_node *node, int index) |
186 | { | 148 | { |
187 | return nilfs_bmap_dkey_to_key(*(nilfs_btree_node_dkeys(node) + index)); | 149 | return le64_to_cpu(*(nilfs_btree_node_dkeys(node) + index)); |
188 | } | 150 | } |
189 | 151 | ||
190 | static inline void | 152 | static void |
191 | nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key) | 153 | nilfs_btree_node_set_key(struct nilfs_btree_node *node, int index, __u64 key) |
192 | { | 154 | { |
193 | *(nilfs_btree_node_dkeys(node) + index) = nilfs_bmap_key_to_dkey(key); | 155 | *(nilfs_btree_node_dkeys(node) + index) = cpu_to_le64(key); |
194 | } | 156 | } |
195 | 157 | ||
196 | static inline __u64 | 158 | static __u64 |
197 | nilfs_btree_node_get_ptr(const struct nilfs_btree *btree, | 159 | nilfs_btree_node_get_ptr(const struct nilfs_btree_node *node, int index, |
198 | const struct nilfs_btree_node *node, int index) | 160 | int ncmax) |
199 | { | 161 | { |
200 | return nilfs_bmap_dptr_to_ptr(*(nilfs_btree_node_dptrs(node, btree) + | 162 | return le64_to_cpu(*(nilfs_btree_node_dptrs(node, ncmax) + index)); |
201 | index)); | ||
202 | } | 163 | } |
203 | 164 | ||
204 | static inline void | 165 | static void |
205 | nilfs_btree_node_set_ptr(struct nilfs_btree *btree, | 166 | nilfs_btree_node_set_ptr(struct nilfs_btree_node *node, int index, __u64 ptr, |
206 | struct nilfs_btree_node *node, int index, __u64 ptr) | 167 | int ncmax) |
207 | { | 168 | { |
208 | *(nilfs_btree_node_dptrs(node, btree) + index) = | 169 | *(nilfs_btree_node_dptrs(node, ncmax) + index) = cpu_to_le64(ptr); |
209 | nilfs_bmap_ptr_to_dptr(ptr); | ||
210 | } | 170 | } |
211 | 171 | ||
212 | static void nilfs_btree_node_init(struct nilfs_btree *btree, | 172 | static void nilfs_btree_node_init(struct nilfs_btree_node *node, int flags, |
213 | struct nilfs_btree_node *node, | 173 | int level, int nchildren, int ncmax, |
214 | int flags, int level, int nchildren, | ||
215 | const __u64 *keys, const __u64 *ptrs) | 174 | const __u64 *keys, const __u64 *ptrs) |
216 | { | 175 | { |
217 | __le64 *dkeys; | 176 | __le64 *dkeys; |
@@ -223,29 +182,28 @@ static void nilfs_btree_node_init(struct nilfs_btree *btree, | |||
223 | nilfs_btree_node_set_nchildren(node, nchildren); | 182 | nilfs_btree_node_set_nchildren(node, nchildren); |
224 | 183 | ||
225 | dkeys = nilfs_btree_node_dkeys(node); | 184 | dkeys = nilfs_btree_node_dkeys(node); |
226 | dptrs = nilfs_btree_node_dptrs(node, btree); | 185 | dptrs = nilfs_btree_node_dptrs(node, ncmax); |
227 | for (i = 0; i < nchildren; i++) { | 186 | for (i = 0; i < nchildren; i++) { |
228 | dkeys[i] = nilfs_bmap_key_to_dkey(keys[i]); | 187 | dkeys[i] = cpu_to_le64(keys[i]); |
229 | dptrs[i] = nilfs_bmap_ptr_to_dptr(ptrs[i]); | 188 | dptrs[i] = cpu_to_le64(ptrs[i]); |
230 | } | 189 | } |
231 | } | 190 | } |
232 | 191 | ||
233 | /* Assume the buffer heads corresponding to left and right are locked. */ | 192 | /* Assume the buffer heads corresponding to left and right are locked. */ |
234 | static void nilfs_btree_node_move_left(struct nilfs_btree *btree, | 193 | static void nilfs_btree_node_move_left(struct nilfs_btree_node *left, |
235 | struct nilfs_btree_node *left, | ||
236 | struct nilfs_btree_node *right, | 194 | struct nilfs_btree_node *right, |
237 | int n) | 195 | int n, int lncmax, int rncmax) |
238 | { | 196 | { |
239 | __le64 *ldkeys, *rdkeys; | 197 | __le64 *ldkeys, *rdkeys; |
240 | __le64 *ldptrs, *rdptrs; | 198 | __le64 *ldptrs, *rdptrs; |
241 | int lnchildren, rnchildren; | 199 | int lnchildren, rnchildren; |
242 | 200 | ||
243 | ldkeys = nilfs_btree_node_dkeys(left); | 201 | ldkeys = nilfs_btree_node_dkeys(left); |
244 | ldptrs = nilfs_btree_node_dptrs(left, btree); | 202 | ldptrs = nilfs_btree_node_dptrs(left, lncmax); |
245 | lnchildren = nilfs_btree_node_get_nchildren(left); | 203 | lnchildren = nilfs_btree_node_get_nchildren(left); |
246 | 204 | ||
247 | rdkeys = nilfs_btree_node_dkeys(right); | 205 | rdkeys = nilfs_btree_node_dkeys(right); |
248 | rdptrs = nilfs_btree_node_dptrs(right, btree); | 206 | rdptrs = nilfs_btree_node_dptrs(right, rncmax); |
249 | rnchildren = nilfs_btree_node_get_nchildren(right); | 207 | rnchildren = nilfs_btree_node_get_nchildren(right); |
250 | 208 | ||
251 | memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys)); | 209 | memcpy(ldkeys + lnchildren, rdkeys, n * sizeof(*rdkeys)); |
@@ -260,21 +218,20 @@ static void nilfs_btree_node_move_left(struct nilfs_btree *btree, | |||
260 | } | 218 | } |
261 | 219 | ||
262 | /* Assume that the buffer heads corresponding to left and right are locked. */ | 220 | /* Assume that the buffer heads corresponding to left and right are locked. */ |
263 | static void nilfs_btree_node_move_right(struct nilfs_btree *btree, | 221 | static void nilfs_btree_node_move_right(struct nilfs_btree_node *left, |
264 | struct nilfs_btree_node *left, | ||
265 | struct nilfs_btree_node *right, | 222 | struct nilfs_btree_node *right, |
266 | int n) | 223 | int n, int lncmax, int rncmax) |
267 | { | 224 | { |
268 | __le64 *ldkeys, *rdkeys; | 225 | __le64 *ldkeys, *rdkeys; |
269 | __le64 *ldptrs, *rdptrs; | 226 | __le64 *ldptrs, *rdptrs; |
270 | int lnchildren, rnchildren; | 227 | int lnchildren, rnchildren; |
271 | 228 | ||
272 | ldkeys = nilfs_btree_node_dkeys(left); | 229 | ldkeys = nilfs_btree_node_dkeys(left); |
273 | ldptrs = nilfs_btree_node_dptrs(left, btree); | 230 | ldptrs = nilfs_btree_node_dptrs(left, lncmax); |
274 | lnchildren = nilfs_btree_node_get_nchildren(left); | 231 | lnchildren = nilfs_btree_node_get_nchildren(left); |
275 | 232 | ||
276 | rdkeys = nilfs_btree_node_dkeys(right); | 233 | rdkeys = nilfs_btree_node_dkeys(right); |
277 | rdptrs = nilfs_btree_node_dptrs(right, btree); | 234 | rdptrs = nilfs_btree_node_dptrs(right, rncmax); |
278 | rnchildren = nilfs_btree_node_get_nchildren(right); | 235 | rnchildren = nilfs_btree_node_get_nchildren(right); |
279 | 236 | ||
280 | memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys)); | 237 | memmove(rdkeys + n, rdkeys, rnchildren * sizeof(*rdkeys)); |
@@ -289,16 +246,15 @@ static void nilfs_btree_node_move_right(struct nilfs_btree *btree, | |||
289 | } | 246 | } |
290 | 247 | ||
291 | /* Assume that the buffer head corresponding to node is locked. */ | 248 | /* Assume that the buffer head corresponding to node is locked. */ |
292 | static void nilfs_btree_node_insert(struct nilfs_btree *btree, | 249 | static void nilfs_btree_node_insert(struct nilfs_btree_node *node, int index, |
293 | struct nilfs_btree_node *node, | 250 | __u64 key, __u64 ptr, int ncmax) |
294 | __u64 key, __u64 ptr, int index) | ||
295 | { | 251 | { |
296 | __le64 *dkeys; | 252 | __le64 *dkeys; |
297 | __le64 *dptrs; | 253 | __le64 *dptrs; |
298 | int nchildren; | 254 | int nchildren; |
299 | 255 | ||
300 | dkeys = nilfs_btree_node_dkeys(node); | 256 | dkeys = nilfs_btree_node_dkeys(node); |
301 | dptrs = nilfs_btree_node_dptrs(node, btree); | 257 | dptrs = nilfs_btree_node_dptrs(node, ncmax); |
302 | nchildren = nilfs_btree_node_get_nchildren(node); | 258 | nchildren = nilfs_btree_node_get_nchildren(node); |
303 | if (index < nchildren) { | 259 | if (index < nchildren) { |
304 | memmove(dkeys + index + 1, dkeys + index, | 260 | memmove(dkeys + index + 1, dkeys + index, |
@@ -306,16 +262,15 @@ static void nilfs_btree_node_insert(struct nilfs_btree *btree, | |||
306 | memmove(dptrs + index + 1, dptrs + index, | 262 | memmove(dptrs + index + 1, dptrs + index, |
307 | (nchildren - index) * sizeof(*dptrs)); | 263 | (nchildren - index) * sizeof(*dptrs)); |
308 | } | 264 | } |
309 | dkeys[index] = nilfs_bmap_key_to_dkey(key); | 265 | dkeys[index] = cpu_to_le64(key); |
310 | dptrs[index] = nilfs_bmap_ptr_to_dptr(ptr); | 266 | dptrs[index] = cpu_to_le64(ptr); |
311 | nchildren++; | 267 | nchildren++; |
312 | nilfs_btree_node_set_nchildren(node, nchildren); | 268 | nilfs_btree_node_set_nchildren(node, nchildren); |
313 | } | 269 | } |
314 | 270 | ||
315 | /* Assume that the buffer head corresponding to node is locked. */ | 271 | /* Assume that the buffer head corresponding to node is locked. */ |
316 | static void nilfs_btree_node_delete(struct nilfs_btree *btree, | 272 | static void nilfs_btree_node_delete(struct nilfs_btree_node *node, int index, |
317 | struct nilfs_btree_node *node, | 273 | __u64 *keyp, __u64 *ptrp, int ncmax) |
318 | __u64 *keyp, __u64 *ptrp, int index) | ||
319 | { | 274 | { |
320 | __u64 key; | 275 | __u64 key; |
321 | __u64 ptr; | 276 | __u64 ptr; |
@@ -324,9 +279,9 @@ static void nilfs_btree_node_delete(struct nilfs_btree *btree, | |||
324 | int nchildren; | 279 | int nchildren; |
325 | 280 | ||
326 | dkeys = nilfs_btree_node_dkeys(node); | 281 | dkeys = nilfs_btree_node_dkeys(node); |
327 | dptrs = nilfs_btree_node_dptrs(node, btree); | 282 | dptrs = nilfs_btree_node_dptrs(node, ncmax); |
328 | key = nilfs_bmap_dkey_to_key(dkeys[index]); | 283 | key = le64_to_cpu(dkeys[index]); |
329 | ptr = nilfs_bmap_dptr_to_ptr(dptrs[index]); | 284 | ptr = le64_to_cpu(dptrs[index]); |
330 | nchildren = nilfs_btree_node_get_nchildren(node); | 285 | nchildren = nilfs_btree_node_get_nchildren(node); |
331 | if (keyp != NULL) | 286 | if (keyp != NULL) |
332 | *keyp = key; | 287 | *keyp = key; |
@@ -382,40 +337,92 @@ static int nilfs_btree_node_lookup(const struct nilfs_btree_node *node, | |||
382 | return s == 0; | 337 | return s == 0; |
383 | } | 338 | } |
384 | 339 | ||
385 | static inline struct nilfs_btree_node * | 340 | /** |
386 | nilfs_btree_get_root(const struct nilfs_btree *btree) | 341 | * nilfs_btree_node_broken - verify consistency of btree node |
342 | * @node: btree node block to be examined | ||
343 | * @size: node size (in bytes) | ||
344 | * @blocknr: block number | ||
345 | * | ||
346 | * Return Value: If node is broken, 1 is returned. Otherwise, 0 is returned. | ||
347 | */ | ||
348 | static int nilfs_btree_node_broken(const struct nilfs_btree_node *node, | ||
349 | size_t size, sector_t blocknr) | ||
387 | { | 350 | { |
388 | return (struct nilfs_btree_node *)btree->bt_bmap.b_u.u_data; | 351 | int level, flags, nchildren; |
352 | int ret = 0; | ||
353 | |||
354 | level = nilfs_btree_node_get_level(node); | ||
355 | flags = nilfs_btree_node_get_flags(node); | ||
356 | nchildren = nilfs_btree_node_get_nchildren(node); | ||
357 | |||
358 | if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN || | ||
359 | level >= NILFS_BTREE_LEVEL_MAX || | ||
360 | (flags & NILFS_BTREE_NODE_ROOT) || | ||
361 | nchildren < 0 || | ||
362 | nchildren > NILFS_BTREE_NODE_NCHILDREN_MAX(size))) { | ||
363 | printk(KERN_CRIT "NILFS: bad btree node (blocknr=%llu): " | ||
364 | "level = %d, flags = 0x%x, nchildren = %d\n", | ||
365 | (unsigned long long)blocknr, level, flags, nchildren); | ||
366 | ret = 1; | ||
367 | } | ||
368 | return ret; | ||
389 | } | 369 | } |
390 | 370 | ||
391 | static inline struct nilfs_btree_node * | 371 | int nilfs_btree_broken_node_block(struct buffer_head *bh) |
372 | { | ||
373 | int ret; | ||
374 | |||
375 | if (buffer_nilfs_checked(bh)) | ||
376 | return 0; | ||
377 | |||
378 | ret = nilfs_btree_node_broken((struct nilfs_btree_node *)bh->b_data, | ||
379 | bh->b_size, bh->b_blocknr); | ||
380 | if (likely(!ret)) | ||
381 | set_buffer_nilfs_checked(bh); | ||
382 | return ret; | ||
383 | } | ||
384 | |||
385 | static struct nilfs_btree_node * | ||
386 | nilfs_btree_get_root(const struct nilfs_bmap *btree) | ||
387 | { | ||
388 | return (struct nilfs_btree_node *)btree->b_u.u_data; | ||
389 | } | ||
390 | |||
391 | static struct nilfs_btree_node * | ||
392 | nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level) | 392 | nilfs_btree_get_nonroot_node(const struct nilfs_btree_path *path, int level) |
393 | { | 393 | { |
394 | return (struct nilfs_btree_node *)path[level].bp_bh->b_data; | 394 | return (struct nilfs_btree_node *)path[level].bp_bh->b_data; |
395 | } | 395 | } |
396 | 396 | ||
397 | static inline struct nilfs_btree_node * | 397 | static struct nilfs_btree_node * |
398 | nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level) | 398 | nilfs_btree_get_sib_node(const struct nilfs_btree_path *path, int level) |
399 | { | 399 | { |
400 | return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data; | 400 | return (struct nilfs_btree_node *)path[level].bp_sib_bh->b_data; |
401 | } | 401 | } |
402 | 402 | ||
403 | static inline int nilfs_btree_height(const struct nilfs_btree *btree) | 403 | static int nilfs_btree_height(const struct nilfs_bmap *btree) |
404 | { | 404 | { |
405 | return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1; | 405 | return nilfs_btree_node_get_level(nilfs_btree_get_root(btree)) + 1; |
406 | } | 406 | } |
407 | 407 | ||
408 | static inline struct nilfs_btree_node * | 408 | static struct nilfs_btree_node * |
409 | nilfs_btree_get_node(const struct nilfs_btree *btree, | 409 | nilfs_btree_get_node(const struct nilfs_bmap *btree, |
410 | const struct nilfs_btree_path *path, | 410 | const struct nilfs_btree_path *path, |
411 | int level) | 411 | int level, int *ncmaxp) |
412 | { | 412 | { |
413 | return (level == nilfs_btree_height(btree) - 1) ? | 413 | struct nilfs_btree_node *node; |
414 | nilfs_btree_get_root(btree) : | 414 | |
415 | nilfs_btree_get_nonroot_node(path, level); | 415 | if (level == nilfs_btree_height(btree) - 1) { |
416 | node = nilfs_btree_get_root(btree); | ||
417 | *ncmaxp = NILFS_BTREE_ROOT_NCHILDREN_MAX; | ||
418 | } else { | ||
419 | node = nilfs_btree_get_nonroot_node(path, level); | ||
420 | *ncmaxp = nilfs_btree_nchildren_per_block(btree); | ||
421 | } | ||
422 | return node; | ||
416 | } | 423 | } |
417 | 424 | ||
418 | static inline int | 425 | static int |
419 | nilfs_btree_bad_node(struct nilfs_btree_node *node, int level) | 426 | nilfs_btree_bad_node(struct nilfs_btree_node *node, int level) |
420 | { | 427 | { |
421 | if (unlikely(nilfs_btree_node_get_level(node) != level)) { | 428 | if (unlikely(nilfs_btree_node_get_level(node) != level)) { |
@@ -427,13 +434,83 @@ nilfs_btree_bad_node(struct nilfs_btree_node *node, int level) | |||
427 | return 0; | 434 | return 0; |
428 | } | 435 | } |
429 | 436 | ||
430 | static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, | 437 | struct nilfs_btree_readahead_info { |
438 | struct nilfs_btree_node *node; /* parent node */ | ||
439 | int max_ra_blocks; /* max nof blocks to read ahead */ | ||
440 | int index; /* current index on the parent node */ | ||
441 | int ncmax; /* nof children in the parent node */ | ||
442 | }; | ||
443 | |||
444 | static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr, | ||
445 | struct buffer_head **bhp, | ||
446 | const struct nilfs_btree_readahead_info *ra) | ||
447 | { | ||
448 | struct address_space *btnc = &NILFS_BMAP_I(btree)->i_btnode_cache; | ||
449 | struct buffer_head *bh, *ra_bh; | ||
450 | sector_t submit_ptr = 0; | ||
451 | int ret; | ||
452 | |||
453 | ret = nilfs_btnode_submit_block(btnc, ptr, 0, READ, &bh, &submit_ptr); | ||
454 | if (ret) { | ||
455 | if (ret != -EEXIST) | ||
456 | return ret; | ||
457 | goto out_check; | ||
458 | } | ||
459 | |||
460 | if (ra) { | ||
461 | int i, n; | ||
462 | __u64 ptr2; | ||
463 | |||
464 | /* read ahead sibling nodes */ | ||
465 | for (n = ra->max_ra_blocks, i = ra->index + 1; | ||
466 | n > 0 && i < ra->ncmax; n--, i++) { | ||
467 | ptr2 = nilfs_btree_node_get_ptr(ra->node, i, ra->ncmax); | ||
468 | |||
469 | ret = nilfs_btnode_submit_block(btnc, ptr2, 0, READA, | ||
470 | &ra_bh, &submit_ptr); | ||
471 | if (likely(!ret || ret == -EEXIST)) | ||
472 | brelse(ra_bh); | ||
473 | else if (ret != -EBUSY) | ||
474 | break; | ||
475 | if (!buffer_locked(bh)) | ||
476 | goto out_no_wait; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | wait_on_buffer(bh); | ||
481 | |||
482 | out_no_wait: | ||
483 | if (!buffer_uptodate(bh)) { | ||
484 | brelse(bh); | ||
485 | return -EIO; | ||
486 | } | ||
487 | |||
488 | out_check: | ||
489 | if (nilfs_btree_broken_node_block(bh)) { | ||
490 | clear_buffer_uptodate(bh); | ||
491 | brelse(bh); | ||
492 | return -EINVAL; | ||
493 | } | ||
494 | |||
495 | *bhp = bh; | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | static int nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr, | ||
500 | struct buffer_head **bhp) | ||
501 | { | ||
502 | return __nilfs_btree_get_block(btree, ptr, bhp, NULL); | ||
503 | } | ||
504 | |||
505 | static int nilfs_btree_do_lookup(const struct nilfs_bmap *btree, | ||
431 | struct nilfs_btree_path *path, | 506 | struct nilfs_btree_path *path, |
432 | __u64 key, __u64 *ptrp, int minlevel) | 507 | __u64 key, __u64 *ptrp, int minlevel, |
508 | int readahead) | ||
433 | { | 509 | { |
434 | struct nilfs_btree_node *node; | 510 | struct nilfs_btree_node *node; |
511 | struct nilfs_btree_readahead_info p, *ra; | ||
435 | __u64 ptr; | 512 | __u64 ptr; |
436 | int level, index, found, ret; | 513 | int level, index, found, ncmax, ret; |
437 | 514 | ||
438 | node = nilfs_btree_get_root(btree); | 515 | node = nilfs_btree_get_root(btree); |
439 | level = nilfs_btree_node_get_level(node); | 516 | level = nilfs_btree_node_get_level(node); |
@@ -441,14 +518,27 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, | |||
441 | return -ENOENT; | 518 | return -ENOENT; |
442 | 519 | ||
443 | found = nilfs_btree_node_lookup(node, key, &index); | 520 | found = nilfs_btree_node_lookup(node, key, &index); |
444 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 521 | ptr = nilfs_btree_node_get_ptr(node, index, |
522 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
445 | path[level].bp_bh = NULL; | 523 | path[level].bp_bh = NULL; |
446 | path[level].bp_index = index; | 524 | path[level].bp_index = index; |
447 | 525 | ||
448 | for (level--; level >= minlevel; level--) { | 526 | ncmax = nilfs_btree_nchildren_per_block(btree); |
449 | ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); | 527 | |
528 | while (--level >= minlevel) { | ||
529 | ra = NULL; | ||
530 | if (level == NILFS_BTREE_LEVEL_NODE_MIN && readahead) { | ||
531 | p.node = nilfs_btree_get_node(btree, path, level + 1, | ||
532 | &p.ncmax); | ||
533 | p.index = index; | ||
534 | p.max_ra_blocks = 7; | ||
535 | ra = &p; | ||
536 | } | ||
537 | ret = __nilfs_btree_get_block(btree, ptr, &path[level].bp_bh, | ||
538 | ra); | ||
450 | if (ret < 0) | 539 | if (ret < 0) |
451 | return ret; | 540 | return ret; |
541 | |||
452 | node = nilfs_btree_get_nonroot_node(path, level); | 542 | node = nilfs_btree_get_nonroot_node(path, level); |
453 | if (nilfs_btree_bad_node(node, level)) | 543 | if (nilfs_btree_bad_node(node, level)) |
454 | return -EINVAL; | 544 | return -EINVAL; |
@@ -456,9 +546,9 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, | |||
456 | found = nilfs_btree_node_lookup(node, key, &index); | 546 | found = nilfs_btree_node_lookup(node, key, &index); |
457 | else | 547 | else |
458 | index = 0; | 548 | index = 0; |
459 | if (index < nilfs_btree_node_nchildren_max(node, btree)) | 549 | if (index < ncmax) { |
460 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 550 | ptr = nilfs_btree_node_get_ptr(node, index, ncmax); |
461 | else { | 551 | } else { |
462 | WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN); | 552 | WARN_ON(found || level != NILFS_BTREE_LEVEL_NODE_MIN); |
463 | /* insert */ | 553 | /* insert */ |
464 | ptr = NILFS_BMAP_INVALID_PTR; | 554 | ptr = NILFS_BMAP_INVALID_PTR; |
@@ -474,22 +564,24 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree, | |||
474 | return 0; | 564 | return 0; |
475 | } | 565 | } |
476 | 566 | ||
477 | static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree, | 567 | static int nilfs_btree_do_lookup_last(const struct nilfs_bmap *btree, |
478 | struct nilfs_btree_path *path, | 568 | struct nilfs_btree_path *path, |
479 | __u64 *keyp, __u64 *ptrp) | 569 | __u64 *keyp, __u64 *ptrp) |
480 | { | 570 | { |
481 | struct nilfs_btree_node *node; | 571 | struct nilfs_btree_node *node; |
482 | __u64 ptr; | 572 | __u64 ptr; |
483 | int index, level, ret; | 573 | int index, level, ncmax, ret; |
484 | 574 | ||
485 | node = nilfs_btree_get_root(btree); | 575 | node = nilfs_btree_get_root(btree); |
486 | index = nilfs_btree_node_get_nchildren(node) - 1; | 576 | index = nilfs_btree_node_get_nchildren(node) - 1; |
487 | if (index < 0) | 577 | if (index < 0) |
488 | return -ENOENT; | 578 | return -ENOENT; |
489 | level = nilfs_btree_node_get_level(node); | 579 | level = nilfs_btree_node_get_level(node); |
490 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 580 | ptr = nilfs_btree_node_get_ptr(node, index, |
581 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
491 | path[level].bp_bh = NULL; | 582 | path[level].bp_bh = NULL; |
492 | path[level].bp_index = index; | 583 | path[level].bp_index = index; |
584 | ncmax = nilfs_btree_nchildren_per_block(btree); | ||
493 | 585 | ||
494 | for (level--; level > 0; level--) { | 586 | for (level--; level > 0; level--) { |
495 | ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); | 587 | ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh); |
@@ -499,7 +591,7 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree, | |||
499 | if (nilfs_btree_bad_node(node, level)) | 591 | if (nilfs_btree_bad_node(node, level)) |
500 | return -EINVAL; | 592 | return -EINVAL; |
501 | index = nilfs_btree_node_get_nchildren(node) - 1; | 593 | index = nilfs_btree_node_get_nchildren(node) - 1; |
502 | ptr = nilfs_btree_node_get_ptr(btree, node, index); | 594 | ptr = nilfs_btree_node_get_ptr(node, index, ncmax); |
503 | path[level].bp_index = index; | 595 | path[level].bp_index = index; |
504 | } | 596 | } |
505 | 597 | ||
@@ -511,51 +603,45 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree, | |||
511 | return 0; | 603 | return 0; |
512 | } | 604 | } |
513 | 605 | ||
514 | static int nilfs_btree_lookup(const struct nilfs_bmap *bmap, | 606 | static int nilfs_btree_lookup(const struct nilfs_bmap *btree, |
515 | __u64 key, int level, __u64 *ptrp) | 607 | __u64 key, int level, __u64 *ptrp) |
516 | { | 608 | { |
517 | struct nilfs_btree *btree; | ||
518 | struct nilfs_btree_path *path; | 609 | struct nilfs_btree_path *path; |
519 | __u64 ptr; | ||
520 | int ret; | 610 | int ret; |
521 | 611 | ||
522 | btree = (struct nilfs_btree *)bmap; | ||
523 | path = nilfs_btree_alloc_path(); | 612 | path = nilfs_btree_alloc_path(); |
524 | if (path == NULL) | 613 | if (path == NULL) |
525 | return -ENOMEM; | 614 | return -ENOMEM; |
526 | 615 | ||
527 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); | 616 | ret = nilfs_btree_do_lookup(btree, path, key, ptrp, level, 0); |
528 | |||
529 | if (ptrp != NULL) | ||
530 | *ptrp = ptr; | ||
531 | 617 | ||
532 | nilfs_btree_free_path(path); | 618 | nilfs_btree_free_path(path); |
533 | 619 | ||
534 | return ret; | 620 | return ret; |
535 | } | 621 | } |
536 | 622 | ||
537 | static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | 623 | static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree, |
538 | __u64 key, __u64 *ptrp, unsigned maxblocks) | 624 | __u64 key, __u64 *ptrp, unsigned maxblocks) |
539 | { | 625 | { |
540 | struct nilfs_btree *btree = (struct nilfs_btree *)bmap; | ||
541 | struct nilfs_btree_path *path; | 626 | struct nilfs_btree_path *path; |
542 | struct nilfs_btree_node *node; | 627 | struct nilfs_btree_node *node; |
543 | struct inode *dat = NULL; | 628 | struct inode *dat = NULL; |
544 | __u64 ptr, ptr2; | 629 | __u64 ptr, ptr2; |
545 | sector_t blocknr; | 630 | sector_t blocknr; |
546 | int level = NILFS_BTREE_LEVEL_NODE_MIN; | 631 | int level = NILFS_BTREE_LEVEL_NODE_MIN; |
547 | int ret, cnt, index, maxlevel; | 632 | int ret, cnt, index, maxlevel, ncmax; |
633 | struct nilfs_btree_readahead_info p; | ||
548 | 634 | ||
549 | path = nilfs_btree_alloc_path(); | 635 | path = nilfs_btree_alloc_path(); |
550 | if (path == NULL) | 636 | if (path == NULL) |
551 | return -ENOMEM; | 637 | return -ENOMEM; |
552 | 638 | ||
553 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level); | 639 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level, 1); |
554 | if (ret < 0) | 640 | if (ret < 0) |
555 | goto out; | 641 | goto out; |
556 | 642 | ||
557 | if (NILFS_BMAP_USE_VBN(bmap)) { | 643 | if (NILFS_BMAP_USE_VBN(btree)) { |
558 | dat = nilfs_bmap_get_dat(bmap); | 644 | dat = nilfs_bmap_get_dat(btree); |
559 | ret = nilfs_dat_translate(dat, ptr, &blocknr); | 645 | ret = nilfs_dat_translate(dat, ptr, &blocknr); |
560 | if (ret < 0) | 646 | if (ret < 0) |
561 | goto out; | 647 | goto out; |
@@ -566,14 +652,14 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
566 | goto end; | 652 | goto end; |
567 | 653 | ||
568 | maxlevel = nilfs_btree_height(btree) - 1; | 654 | maxlevel = nilfs_btree_height(btree) - 1; |
569 | node = nilfs_btree_get_node(btree, path, level); | 655 | node = nilfs_btree_get_node(btree, path, level, &ncmax); |
570 | index = path[level].bp_index + 1; | 656 | index = path[level].bp_index + 1; |
571 | for (;;) { | 657 | for (;;) { |
572 | while (index < nilfs_btree_node_get_nchildren(node)) { | 658 | while (index < nilfs_btree_node_get_nchildren(node)) { |
573 | if (nilfs_btree_node_get_key(node, index) != | 659 | if (nilfs_btree_node_get_key(node, index) != |
574 | key + cnt) | 660 | key + cnt) |
575 | goto end; | 661 | goto end; |
576 | ptr2 = nilfs_btree_node_get_ptr(btree, node, index); | 662 | ptr2 = nilfs_btree_node_get_ptr(node, index, ncmax); |
577 | if (dat) { | 663 | if (dat) { |
578 | ret = nilfs_dat_translate(dat, ptr2, &blocknr); | 664 | ret = nilfs_dat_translate(dat, ptr2, &blocknr); |
579 | if (ret < 0) | 665 | if (ret < 0) |
@@ -589,20 +675,24 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
589 | break; | 675 | break; |
590 | 676 | ||
591 | /* look-up right sibling node */ | 677 | /* look-up right sibling node */ |
592 | node = nilfs_btree_get_node(btree, path, level + 1); | 678 | p.node = nilfs_btree_get_node(btree, path, level + 1, &p.ncmax); |
593 | index = path[level + 1].bp_index + 1; | 679 | p.index = path[level + 1].bp_index + 1; |
594 | if (index >= nilfs_btree_node_get_nchildren(node) || | 680 | p.max_ra_blocks = 7; |
595 | nilfs_btree_node_get_key(node, index) != key + cnt) | 681 | if (p.index >= nilfs_btree_node_get_nchildren(p.node) || |
682 | nilfs_btree_node_get_key(p.node, p.index) != key + cnt) | ||
596 | break; | 683 | break; |
597 | ptr2 = nilfs_btree_node_get_ptr(btree, node, index); | 684 | ptr2 = nilfs_btree_node_get_ptr(p.node, p.index, p.ncmax); |
598 | path[level + 1].bp_index = index; | 685 | path[level + 1].bp_index = p.index; |
599 | 686 | ||
600 | brelse(path[level].bp_bh); | 687 | brelse(path[level].bp_bh); |
601 | path[level].bp_bh = NULL; | 688 | path[level].bp_bh = NULL; |
602 | ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh); | 689 | |
690 | ret = __nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh, | ||
691 | &p); | ||
603 | if (ret < 0) | 692 | if (ret < 0) |
604 | goto out; | 693 | goto out; |
605 | node = nilfs_btree_get_nonroot_node(path, level); | 694 | node = nilfs_btree_get_nonroot_node(path, level); |
695 | ncmax = nilfs_btree_nchildren_per_block(btree); | ||
606 | index = 0; | 696 | index = 0; |
607 | path[level].bp_index = index; | 697 | path[level].bp_index = index; |
608 | } | 698 | } |
@@ -614,7 +704,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap, | |||
614 | return ret; | 704 | return ret; |
615 | } | 705 | } |
616 | 706 | ||
617 | static void nilfs_btree_promote_key(struct nilfs_btree *btree, | 707 | static void nilfs_btree_promote_key(struct nilfs_bmap *btree, |
618 | struct nilfs_btree_path *path, | 708 | struct nilfs_btree_path *path, |
619 | int level, __u64 key) | 709 | int level, __u64 key) |
620 | { | 710 | { |
@@ -636,16 +726,18 @@ static void nilfs_btree_promote_key(struct nilfs_btree *btree, | |||
636 | } | 726 | } |
637 | } | 727 | } |
638 | 728 | ||
639 | static void nilfs_btree_do_insert(struct nilfs_btree *btree, | 729 | static void nilfs_btree_do_insert(struct nilfs_bmap *btree, |
640 | struct nilfs_btree_path *path, | 730 | struct nilfs_btree_path *path, |
641 | int level, __u64 *keyp, __u64 *ptrp) | 731 | int level, __u64 *keyp, __u64 *ptrp) |
642 | { | 732 | { |
643 | struct nilfs_btree_node *node; | 733 | struct nilfs_btree_node *node; |
734 | int ncblk; | ||
644 | 735 | ||
645 | if (level < nilfs_btree_height(btree) - 1) { | 736 | if (level < nilfs_btree_height(btree) - 1) { |
646 | node = nilfs_btree_get_nonroot_node(path, level); | 737 | node = nilfs_btree_get_nonroot_node(path, level); |
647 | nilfs_btree_node_insert(btree, node, *keyp, *ptrp, | 738 | ncblk = nilfs_btree_nchildren_per_block(btree); |
648 | path[level].bp_index); | 739 | nilfs_btree_node_insert(node, path[level].bp_index, |
740 | *keyp, *ptrp, ncblk); | ||
649 | if (!buffer_dirty(path[level].bp_bh)) | 741 | if (!buffer_dirty(path[level].bp_bh)) |
650 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 742 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
651 | 743 | ||
@@ -655,22 +747,24 @@ static void nilfs_btree_do_insert(struct nilfs_btree *btree, | |||
655 | 0)); | 747 | 0)); |
656 | } else { | 748 | } else { |
657 | node = nilfs_btree_get_root(btree); | 749 | node = nilfs_btree_get_root(btree); |
658 | nilfs_btree_node_insert(btree, node, *keyp, *ptrp, | 750 | nilfs_btree_node_insert(node, path[level].bp_index, |
659 | path[level].bp_index); | 751 | *keyp, *ptrp, |
752 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
660 | } | 753 | } |
661 | } | 754 | } |
662 | 755 | ||
663 | static void nilfs_btree_carry_left(struct nilfs_btree *btree, | 756 | static void nilfs_btree_carry_left(struct nilfs_bmap *btree, |
664 | struct nilfs_btree_path *path, | 757 | struct nilfs_btree_path *path, |
665 | int level, __u64 *keyp, __u64 *ptrp) | 758 | int level, __u64 *keyp, __u64 *ptrp) |
666 | { | 759 | { |
667 | struct nilfs_btree_node *node, *left; | 760 | struct nilfs_btree_node *node, *left; |
668 | int nchildren, lnchildren, n, move; | 761 | int nchildren, lnchildren, n, move, ncblk; |
669 | 762 | ||
670 | node = nilfs_btree_get_nonroot_node(path, level); | 763 | node = nilfs_btree_get_nonroot_node(path, level); |
671 | left = nilfs_btree_get_sib_node(path, level); | 764 | left = nilfs_btree_get_sib_node(path, level); |
672 | nchildren = nilfs_btree_node_get_nchildren(node); | 765 | nchildren = nilfs_btree_node_get_nchildren(node); |
673 | lnchildren = nilfs_btree_node_get_nchildren(left); | 766 | lnchildren = nilfs_btree_node_get_nchildren(left); |
767 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
674 | move = 0; | 768 | move = 0; |
675 | 769 | ||
676 | n = (nchildren + lnchildren + 1) / 2 - lnchildren; | 770 | n = (nchildren + lnchildren + 1) / 2 - lnchildren; |
@@ -680,7 +774,7 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree, | |||
680 | move = 1; | 774 | move = 1; |
681 | } | 775 | } |
682 | 776 | ||
683 | nilfs_btree_node_move_left(btree, left, node, n); | 777 | nilfs_btree_node_move_left(left, node, n, ncblk, ncblk); |
684 | 778 | ||
685 | if (!buffer_dirty(path[level].bp_bh)) | 779 | if (!buffer_dirty(path[level].bp_bh)) |
686 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 780 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -705,17 +799,18 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree, | |||
705 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); | 799 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); |
706 | } | 800 | } |
707 | 801 | ||
708 | static void nilfs_btree_carry_right(struct nilfs_btree *btree, | 802 | static void nilfs_btree_carry_right(struct nilfs_bmap *btree, |
709 | struct nilfs_btree_path *path, | 803 | struct nilfs_btree_path *path, |
710 | int level, __u64 *keyp, __u64 *ptrp) | 804 | int level, __u64 *keyp, __u64 *ptrp) |
711 | { | 805 | { |
712 | struct nilfs_btree_node *node, *right; | 806 | struct nilfs_btree_node *node, *right; |
713 | int nchildren, rnchildren, n, move; | 807 | int nchildren, rnchildren, n, move, ncblk; |
714 | 808 | ||
715 | node = nilfs_btree_get_nonroot_node(path, level); | 809 | node = nilfs_btree_get_nonroot_node(path, level); |
716 | right = nilfs_btree_get_sib_node(path, level); | 810 | right = nilfs_btree_get_sib_node(path, level); |
717 | nchildren = nilfs_btree_node_get_nchildren(node); | 811 | nchildren = nilfs_btree_node_get_nchildren(node); |
718 | rnchildren = nilfs_btree_node_get_nchildren(right); | 812 | rnchildren = nilfs_btree_node_get_nchildren(right); |
813 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
719 | move = 0; | 814 | move = 0; |
720 | 815 | ||
721 | n = (nchildren + rnchildren + 1) / 2 - rnchildren; | 816 | n = (nchildren + rnchildren + 1) / 2 - rnchildren; |
@@ -725,7 +820,7 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree, | |||
725 | move = 1; | 820 | move = 1; |
726 | } | 821 | } |
727 | 822 | ||
728 | nilfs_btree_node_move_right(btree, node, right, n); | 823 | nilfs_btree_node_move_right(node, right, n, ncblk, ncblk); |
729 | 824 | ||
730 | if (!buffer_dirty(path[level].bp_bh)) | 825 | if (!buffer_dirty(path[level].bp_bh)) |
731 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 826 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -751,18 +846,19 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree, | |||
751 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); | 846 | nilfs_btree_do_insert(btree, path, level, keyp, ptrp); |
752 | } | 847 | } |
753 | 848 | ||
754 | static void nilfs_btree_split(struct nilfs_btree *btree, | 849 | static void nilfs_btree_split(struct nilfs_bmap *btree, |
755 | struct nilfs_btree_path *path, | 850 | struct nilfs_btree_path *path, |
756 | int level, __u64 *keyp, __u64 *ptrp) | 851 | int level, __u64 *keyp, __u64 *ptrp) |
757 | { | 852 | { |
758 | struct nilfs_btree_node *node, *right; | 853 | struct nilfs_btree_node *node, *right; |
759 | __u64 newkey; | 854 | __u64 newkey; |
760 | __u64 newptr; | 855 | __u64 newptr; |
761 | int nchildren, n, move; | 856 | int nchildren, n, move, ncblk; |
762 | 857 | ||
763 | node = nilfs_btree_get_nonroot_node(path, level); | 858 | node = nilfs_btree_get_nonroot_node(path, level); |
764 | right = nilfs_btree_get_sib_node(path, level); | 859 | right = nilfs_btree_get_sib_node(path, level); |
765 | nchildren = nilfs_btree_node_get_nchildren(node); | 860 | nchildren = nilfs_btree_node_get_nchildren(node); |
861 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
766 | move = 0; | 862 | move = 0; |
767 | 863 | ||
768 | n = (nchildren + 1) / 2; | 864 | n = (nchildren + 1) / 2; |
@@ -771,7 +867,7 @@ static void nilfs_btree_split(struct nilfs_btree *btree, | |||
771 | move = 1; | 867 | move = 1; |
772 | } | 868 | } |
773 | 869 | ||
774 | nilfs_btree_node_move_right(btree, node, right, n); | 870 | nilfs_btree_node_move_right(node, right, n, ncblk, ncblk); |
775 | 871 | ||
776 | if (!buffer_dirty(path[level].bp_bh)) | 872 | if (!buffer_dirty(path[level].bp_bh)) |
777 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 873 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -783,8 +879,8 @@ static void nilfs_btree_split(struct nilfs_btree *btree, | |||
783 | 879 | ||
784 | if (move) { | 880 | if (move) { |
785 | path[level].bp_index -= nilfs_btree_node_get_nchildren(node); | 881 | path[level].bp_index -= nilfs_btree_node_get_nchildren(node); |
786 | nilfs_btree_node_insert(btree, right, *keyp, *ptrp, | 882 | nilfs_btree_node_insert(right, path[level].bp_index, |
787 | path[level].bp_index); | 883 | *keyp, *ptrp, ncblk); |
788 | 884 | ||
789 | *keyp = nilfs_btree_node_get_key(right, 0); | 885 | *keyp = nilfs_btree_node_get_key(right, 0); |
790 | *ptrp = path[level].bp_newreq.bpr_ptr; | 886 | *ptrp = path[level].bp_newreq.bpr_ptr; |
@@ -805,19 +901,21 @@ static void nilfs_btree_split(struct nilfs_btree *btree, | |||
805 | path[level + 1].bp_index++; | 901 | path[level + 1].bp_index++; |
806 | } | 902 | } |
807 | 903 | ||
808 | static void nilfs_btree_grow(struct nilfs_btree *btree, | 904 | static void nilfs_btree_grow(struct nilfs_bmap *btree, |
809 | struct nilfs_btree_path *path, | 905 | struct nilfs_btree_path *path, |
810 | int level, __u64 *keyp, __u64 *ptrp) | 906 | int level, __u64 *keyp, __u64 *ptrp) |
811 | { | 907 | { |
812 | struct nilfs_btree_node *root, *child; | 908 | struct nilfs_btree_node *root, *child; |
813 | int n; | 909 | int n, ncblk; |
814 | 910 | ||
815 | root = nilfs_btree_get_root(btree); | 911 | root = nilfs_btree_get_root(btree); |
816 | child = nilfs_btree_get_sib_node(path, level); | 912 | child = nilfs_btree_get_sib_node(path, level); |
913 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
817 | 914 | ||
818 | n = nilfs_btree_node_get_nchildren(root); | 915 | n = nilfs_btree_node_get_nchildren(root); |
819 | 916 | ||
820 | nilfs_btree_node_move_right(btree, root, child, n); | 917 | nilfs_btree_node_move_right(root, child, n, |
918 | NILFS_BTREE_ROOT_NCHILDREN_MAX, ncblk); | ||
821 | nilfs_btree_node_set_level(root, level + 1); | 919 | nilfs_btree_node_set_level(root, level + 1); |
822 | 920 | ||
823 | if (!buffer_dirty(path[level].bp_sib_bh)) | 921 | if (!buffer_dirty(path[level].bp_sib_bh)) |
@@ -832,11 +930,11 @@ static void nilfs_btree_grow(struct nilfs_btree *btree, | |||
832 | *ptrp = path[level].bp_newreq.bpr_ptr; | 930 | *ptrp = path[level].bp_newreq.bpr_ptr; |
833 | } | 931 | } |
834 | 932 | ||
835 | static __u64 nilfs_btree_find_near(const struct nilfs_btree *btree, | 933 | static __u64 nilfs_btree_find_near(const struct nilfs_bmap *btree, |
836 | const struct nilfs_btree_path *path) | 934 | const struct nilfs_btree_path *path) |
837 | { | 935 | { |
838 | struct nilfs_btree_node *node; | 936 | struct nilfs_btree_node *node; |
839 | int level; | 937 | int level, ncmax; |
840 | 938 | ||
841 | if (path == NULL) | 939 | if (path == NULL) |
842 | return NILFS_BMAP_INVALID_PTR; | 940 | return NILFS_BMAP_INVALID_PTR; |
@@ -844,29 +942,30 @@ static __u64 nilfs_btree_find_near(const struct nilfs_btree *btree, | |||
844 | /* left sibling */ | 942 | /* left sibling */ |
845 | level = NILFS_BTREE_LEVEL_NODE_MIN; | 943 | level = NILFS_BTREE_LEVEL_NODE_MIN; |
846 | if (path[level].bp_index > 0) { | 944 | if (path[level].bp_index > 0) { |
847 | node = nilfs_btree_get_node(btree, path, level); | 945 | node = nilfs_btree_get_node(btree, path, level, &ncmax); |
848 | return nilfs_btree_node_get_ptr(btree, node, | 946 | return nilfs_btree_node_get_ptr(node, |
849 | path[level].bp_index - 1); | 947 | path[level].bp_index - 1, |
948 | ncmax); | ||
850 | } | 949 | } |
851 | 950 | ||
852 | /* parent */ | 951 | /* parent */ |
853 | level = NILFS_BTREE_LEVEL_NODE_MIN + 1; | 952 | level = NILFS_BTREE_LEVEL_NODE_MIN + 1; |
854 | if (level <= nilfs_btree_height(btree) - 1) { | 953 | if (level <= nilfs_btree_height(btree) - 1) { |
855 | node = nilfs_btree_get_node(btree, path, level); | 954 | node = nilfs_btree_get_node(btree, path, level, &ncmax); |
856 | return nilfs_btree_node_get_ptr(btree, node, | 955 | return nilfs_btree_node_get_ptr(node, path[level].bp_index, |
857 | path[level].bp_index); | 956 | ncmax); |
858 | } | 957 | } |
859 | 958 | ||
860 | return NILFS_BMAP_INVALID_PTR; | 959 | return NILFS_BMAP_INVALID_PTR; |
861 | } | 960 | } |
862 | 961 | ||
863 | static __u64 nilfs_btree_find_target_v(const struct nilfs_btree *btree, | 962 | static __u64 nilfs_btree_find_target_v(const struct nilfs_bmap *btree, |
864 | const struct nilfs_btree_path *path, | 963 | const struct nilfs_btree_path *path, |
865 | __u64 key) | 964 | __u64 key) |
866 | { | 965 | { |
867 | __u64 ptr; | 966 | __u64 ptr; |
868 | 967 | ||
869 | ptr = nilfs_bmap_find_target_seq(&btree->bt_bmap, key); | 968 | ptr = nilfs_bmap_find_target_seq(btree, key); |
870 | if (ptr != NILFS_BMAP_INVALID_PTR) | 969 | if (ptr != NILFS_BMAP_INVALID_PTR) |
871 | /* sequential access */ | 970 | /* sequential access */ |
872 | return ptr; | 971 | return ptr; |
@@ -877,17 +976,10 @@ static __u64 nilfs_btree_find_target_v(const struct nilfs_btree *btree, | |||
877 | return ptr; | 976 | return ptr; |
878 | } | 977 | } |
879 | /* block group */ | 978 | /* block group */ |
880 | return nilfs_bmap_find_target_in_group(&btree->bt_bmap); | 979 | return nilfs_bmap_find_target_in_group(btree); |
881 | } | ||
882 | |||
883 | static void nilfs_btree_set_target_v(struct nilfs_btree *btree, __u64 key, | ||
884 | __u64 ptr) | ||
885 | { | ||
886 | btree->bt_bmap.b_last_allocated_key = key; | ||
887 | btree->bt_bmap.b_last_allocated_ptr = ptr; | ||
888 | } | 980 | } |
889 | 981 | ||
890 | static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | 982 | static int nilfs_btree_prepare_insert(struct nilfs_bmap *btree, |
891 | struct nilfs_btree_path *path, | 983 | struct nilfs_btree_path *path, |
892 | int *levelp, __u64 key, __u64 ptr, | 984 | int *levelp, __u64 key, __u64 ptr, |
893 | struct nilfs_bmap_stats *stats) | 985 | struct nilfs_bmap_stats *stats) |
@@ -895,79 +987,78 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
895 | struct buffer_head *bh; | 987 | struct buffer_head *bh; |
896 | struct nilfs_btree_node *node, *parent, *sib; | 988 | struct nilfs_btree_node *node, *parent, *sib; |
897 | __u64 sibptr; | 989 | __u64 sibptr; |
898 | int pindex, level, ret; | 990 | int pindex, level, ncmax, ncblk, ret; |
899 | struct inode *dat = NULL; | 991 | struct inode *dat = NULL; |
900 | 992 | ||
901 | stats->bs_nblocks = 0; | 993 | stats->bs_nblocks = 0; |
902 | level = NILFS_BTREE_LEVEL_DATA; | 994 | level = NILFS_BTREE_LEVEL_DATA; |
903 | 995 | ||
904 | /* allocate a new ptr for data block */ | 996 | /* allocate a new ptr for data block */ |
905 | if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) { | 997 | if (NILFS_BMAP_USE_VBN(btree)) { |
906 | path[level].bp_newreq.bpr_ptr = | 998 | path[level].bp_newreq.bpr_ptr = |
907 | nilfs_btree_find_target_v(btree, path, key); | 999 | nilfs_btree_find_target_v(btree, path, key); |
908 | dat = nilfs_bmap_get_dat(&btree->bt_bmap); | 1000 | dat = nilfs_bmap_get_dat(btree); |
909 | } | 1001 | } |
910 | 1002 | ||
911 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, | 1003 | ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat); |
912 | &path[level].bp_newreq, dat); | ||
913 | if (ret < 0) | 1004 | if (ret < 0) |
914 | goto err_out_data; | 1005 | goto err_out_data; |
915 | 1006 | ||
1007 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1008 | |||
916 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; | 1009 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; |
917 | level < nilfs_btree_height(btree) - 1; | 1010 | level < nilfs_btree_height(btree) - 1; |
918 | level++) { | 1011 | level++) { |
919 | node = nilfs_btree_get_nonroot_node(path, level); | 1012 | node = nilfs_btree_get_nonroot_node(path, level); |
920 | if (nilfs_btree_node_get_nchildren(node) < | 1013 | if (nilfs_btree_node_get_nchildren(node) < ncblk) { |
921 | nilfs_btree_node_nchildren_max(node, btree)) { | ||
922 | path[level].bp_op = nilfs_btree_do_insert; | 1014 | path[level].bp_op = nilfs_btree_do_insert; |
923 | stats->bs_nblocks++; | 1015 | stats->bs_nblocks++; |
924 | goto out; | 1016 | goto out; |
925 | } | 1017 | } |
926 | 1018 | ||
927 | parent = nilfs_btree_get_node(btree, path, level + 1); | 1019 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
928 | pindex = path[level + 1].bp_index; | 1020 | pindex = path[level + 1].bp_index; |
929 | 1021 | ||
930 | /* left sibling */ | 1022 | /* left sibling */ |
931 | if (pindex > 0) { | 1023 | if (pindex > 0) { |
932 | sibptr = nilfs_btree_node_get_ptr(btree, parent, | 1024 | sibptr = nilfs_btree_node_get_ptr(parent, pindex - 1, |
933 | pindex - 1); | 1025 | ncmax); |
934 | ret = nilfs_btree_get_block(btree, sibptr, &bh); | 1026 | ret = nilfs_btree_get_block(btree, sibptr, &bh); |
935 | if (ret < 0) | 1027 | if (ret < 0) |
936 | goto err_out_child_node; | 1028 | goto err_out_child_node; |
937 | sib = (struct nilfs_btree_node *)bh->b_data; | 1029 | sib = (struct nilfs_btree_node *)bh->b_data; |
938 | if (nilfs_btree_node_get_nchildren(sib) < | 1030 | if (nilfs_btree_node_get_nchildren(sib) < ncblk) { |
939 | nilfs_btree_node_nchildren_max(sib, btree)) { | ||
940 | path[level].bp_sib_bh = bh; | 1031 | path[level].bp_sib_bh = bh; |
941 | path[level].bp_op = nilfs_btree_carry_left; | 1032 | path[level].bp_op = nilfs_btree_carry_left; |
942 | stats->bs_nblocks++; | 1033 | stats->bs_nblocks++; |
943 | goto out; | 1034 | goto out; |
944 | } else | 1035 | } else { |
945 | brelse(bh); | 1036 | brelse(bh); |
1037 | } | ||
946 | } | 1038 | } |
947 | 1039 | ||
948 | /* right sibling */ | 1040 | /* right sibling */ |
949 | if (pindex < | 1041 | if (pindex < nilfs_btree_node_get_nchildren(parent) - 1) { |
950 | nilfs_btree_node_get_nchildren(parent) - 1) { | 1042 | sibptr = nilfs_btree_node_get_ptr(parent, pindex + 1, |
951 | sibptr = nilfs_btree_node_get_ptr(btree, parent, | 1043 | ncmax); |
952 | pindex + 1); | ||
953 | ret = nilfs_btree_get_block(btree, sibptr, &bh); | 1044 | ret = nilfs_btree_get_block(btree, sibptr, &bh); |
954 | if (ret < 0) | 1045 | if (ret < 0) |
955 | goto err_out_child_node; | 1046 | goto err_out_child_node; |
956 | sib = (struct nilfs_btree_node *)bh->b_data; | 1047 | sib = (struct nilfs_btree_node *)bh->b_data; |
957 | if (nilfs_btree_node_get_nchildren(sib) < | 1048 | if (nilfs_btree_node_get_nchildren(sib) < ncblk) { |
958 | nilfs_btree_node_nchildren_max(sib, btree)) { | ||
959 | path[level].bp_sib_bh = bh; | 1049 | path[level].bp_sib_bh = bh; |
960 | path[level].bp_op = nilfs_btree_carry_right; | 1050 | path[level].bp_op = nilfs_btree_carry_right; |
961 | stats->bs_nblocks++; | 1051 | stats->bs_nblocks++; |
962 | goto out; | 1052 | goto out; |
963 | } else | 1053 | } else { |
964 | brelse(bh); | 1054 | brelse(bh); |
1055 | } | ||
965 | } | 1056 | } |
966 | 1057 | ||
967 | /* split */ | 1058 | /* split */ |
968 | path[level].bp_newreq.bpr_ptr = | 1059 | path[level].bp_newreq.bpr_ptr = |
969 | path[level - 1].bp_newreq.bpr_ptr + 1; | 1060 | path[level - 1].bp_newreq.bpr_ptr + 1; |
970 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, | 1061 | ret = nilfs_bmap_prepare_alloc_ptr(btree, |
971 | &path[level].bp_newreq, dat); | 1062 | &path[level].bp_newreq, dat); |
972 | if (ret < 0) | 1063 | if (ret < 0) |
973 | goto err_out_child_node; | 1064 | goto err_out_child_node; |
@@ -979,9 +1070,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
979 | 1070 | ||
980 | stats->bs_nblocks++; | 1071 | stats->bs_nblocks++; |
981 | 1072 | ||
982 | nilfs_btree_node_init(btree, | 1073 | sib = (struct nilfs_btree_node *)bh->b_data; |
983 | (struct nilfs_btree_node *)bh->b_data, | 1074 | nilfs_btree_node_init(sib, 0, level, 0, ncblk, NULL, NULL); |
984 | 0, level, 0, NULL, NULL); | ||
985 | path[level].bp_sib_bh = bh; | 1075 | path[level].bp_sib_bh = bh; |
986 | path[level].bp_op = nilfs_btree_split; | 1076 | path[level].bp_op = nilfs_btree_split; |
987 | } | 1077 | } |
@@ -989,7 +1079,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
989 | /* root */ | 1079 | /* root */ |
990 | node = nilfs_btree_get_root(btree); | 1080 | node = nilfs_btree_get_root(btree); |
991 | if (nilfs_btree_node_get_nchildren(node) < | 1081 | if (nilfs_btree_node_get_nchildren(node) < |
992 | nilfs_btree_node_nchildren_max(node, btree)) { | 1082 | NILFS_BTREE_ROOT_NCHILDREN_MAX) { |
993 | path[level].bp_op = nilfs_btree_do_insert; | 1083 | path[level].bp_op = nilfs_btree_do_insert; |
994 | stats->bs_nblocks++; | 1084 | stats->bs_nblocks++; |
995 | goto out; | 1085 | goto out; |
@@ -997,8 +1087,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
997 | 1087 | ||
998 | /* grow */ | 1088 | /* grow */ |
999 | path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1; | 1089 | path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1; |
1000 | ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap, | 1090 | ret = nilfs_bmap_prepare_alloc_ptr(btree, &path[level].bp_newreq, dat); |
1001 | &path[level].bp_newreq, dat); | ||
1002 | if (ret < 0) | 1091 | if (ret < 0) |
1003 | goto err_out_child_node; | 1092 | goto err_out_child_node; |
1004 | ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr, | 1093 | ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr, |
@@ -1006,8 +1095,8 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
1006 | if (ret < 0) | 1095 | if (ret < 0) |
1007 | goto err_out_curr_node; | 1096 | goto err_out_curr_node; |
1008 | 1097 | ||
1009 | nilfs_btree_node_init(btree, (struct nilfs_btree_node *)bh->b_data, | 1098 | nilfs_btree_node_init((struct nilfs_btree_node *)bh->b_data, |
1010 | 0, level, 0, NULL, NULL); | 1099 | 0, level, 0, ncblk, NULL, NULL); |
1011 | path[level].bp_sib_bh = bh; | 1100 | path[level].bp_sib_bh = bh; |
1012 | path[level].bp_op = nilfs_btree_grow; | 1101 | path[level].bp_op = nilfs_btree_grow; |
1013 | 1102 | ||
@@ -1024,25 +1113,22 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree, | |||
1024 | 1113 | ||
1025 | /* error */ | 1114 | /* error */ |
1026 | err_out_curr_node: | 1115 | err_out_curr_node: |
1027 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq, | 1116 | nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat); |
1028 | dat); | ||
1029 | err_out_child_node: | 1117 | err_out_child_node: |
1030 | for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) { | 1118 | for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) { |
1031 | nilfs_btnode_delete(path[level].bp_sib_bh); | 1119 | nilfs_btnode_delete(path[level].bp_sib_bh); |
1032 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, | 1120 | nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat); |
1033 | &path[level].bp_newreq, dat); | ||
1034 | 1121 | ||
1035 | } | 1122 | } |
1036 | 1123 | ||
1037 | nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq, | 1124 | nilfs_bmap_abort_alloc_ptr(btree, &path[level].bp_newreq, dat); |
1038 | dat); | ||
1039 | err_out_data: | 1125 | err_out_data: |
1040 | *levelp = level; | 1126 | *levelp = level; |
1041 | stats->bs_nblocks = 0; | 1127 | stats->bs_nblocks = 0; |
1042 | return ret; | 1128 | return ret; |
1043 | } | 1129 | } |
1044 | 1130 | ||
1045 | static void nilfs_btree_commit_insert(struct nilfs_btree *btree, | 1131 | static void nilfs_btree_commit_insert(struct nilfs_bmap *btree, |
1046 | struct nilfs_btree_path *path, | 1132 | struct nilfs_btree_path *path, |
1047 | int maxlevel, __u64 key, __u64 ptr) | 1133 | int maxlevel, __u64 key, __u64 ptr) |
1048 | { | 1134 | { |
@@ -1051,35 +1137,33 @@ static void nilfs_btree_commit_insert(struct nilfs_btree *btree, | |||
1051 | 1137 | ||
1052 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); | 1138 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); |
1053 | ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr; | 1139 | ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr; |
1054 | if (NILFS_BMAP_USE_VBN(&btree->bt_bmap)) { | 1140 | if (NILFS_BMAP_USE_VBN(btree)) { |
1055 | nilfs_btree_set_target_v(btree, key, ptr); | 1141 | nilfs_bmap_set_target_v(btree, key, ptr); |
1056 | dat = nilfs_bmap_get_dat(&btree->bt_bmap); | 1142 | dat = nilfs_bmap_get_dat(btree); |
1057 | } | 1143 | } |
1058 | 1144 | ||
1059 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { | 1145 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { |
1060 | nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap, | 1146 | nilfs_bmap_commit_alloc_ptr(btree, |
1061 | &path[level - 1].bp_newreq, dat); | 1147 | &path[level - 1].bp_newreq, dat); |
1062 | path[level].bp_op(btree, path, level, &key, &ptr); | 1148 | path[level].bp_op(btree, path, level, &key, &ptr); |
1063 | } | 1149 | } |
1064 | 1150 | ||
1065 | if (!nilfs_bmap_dirty(&btree->bt_bmap)) | 1151 | if (!nilfs_bmap_dirty(btree)) |
1066 | nilfs_bmap_set_dirty(&btree->bt_bmap); | 1152 | nilfs_bmap_set_dirty(btree); |
1067 | } | 1153 | } |
1068 | 1154 | ||
1069 | static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | 1155 | static int nilfs_btree_insert(struct nilfs_bmap *btree, __u64 key, __u64 ptr) |
1070 | { | 1156 | { |
1071 | struct nilfs_btree *btree; | ||
1072 | struct nilfs_btree_path *path; | 1157 | struct nilfs_btree_path *path; |
1073 | struct nilfs_bmap_stats stats; | 1158 | struct nilfs_bmap_stats stats; |
1074 | int level, ret; | 1159 | int level, ret; |
1075 | 1160 | ||
1076 | btree = (struct nilfs_btree *)bmap; | ||
1077 | path = nilfs_btree_alloc_path(); | 1161 | path = nilfs_btree_alloc_path(); |
1078 | if (path == NULL) | 1162 | if (path == NULL) |
1079 | return -ENOMEM; | 1163 | return -ENOMEM; |
1080 | 1164 | ||
1081 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, | 1165 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, |
1082 | NILFS_BTREE_LEVEL_NODE_MIN); | 1166 | NILFS_BTREE_LEVEL_NODE_MIN, 0); |
1083 | if (ret != -ENOENT) { | 1167 | if (ret != -ENOENT) { |
1084 | if (ret == 0) | 1168 | if (ret == 0) |
1085 | ret = -EEXIST; | 1169 | ret = -EEXIST; |
@@ -1090,23 +1174,25 @@ static int nilfs_btree_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
1090 | if (ret < 0) | 1174 | if (ret < 0) |
1091 | goto out; | 1175 | goto out; |
1092 | nilfs_btree_commit_insert(btree, path, level, key, ptr); | 1176 | nilfs_btree_commit_insert(btree, path, level, key, ptr); |
1093 | nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); | 1177 | nilfs_bmap_add_blocks(btree, stats.bs_nblocks); |
1094 | 1178 | ||
1095 | out: | 1179 | out: |
1096 | nilfs_btree_free_path(path); | 1180 | nilfs_btree_free_path(path); |
1097 | return ret; | 1181 | return ret; |
1098 | } | 1182 | } |
1099 | 1183 | ||
1100 | static void nilfs_btree_do_delete(struct nilfs_btree *btree, | 1184 | static void nilfs_btree_do_delete(struct nilfs_bmap *btree, |
1101 | struct nilfs_btree_path *path, | 1185 | struct nilfs_btree_path *path, |
1102 | int level, __u64 *keyp, __u64 *ptrp) | 1186 | int level, __u64 *keyp, __u64 *ptrp) |
1103 | { | 1187 | { |
1104 | struct nilfs_btree_node *node; | 1188 | struct nilfs_btree_node *node; |
1189 | int ncblk; | ||
1105 | 1190 | ||
1106 | if (level < nilfs_btree_height(btree) - 1) { | 1191 | if (level < nilfs_btree_height(btree) - 1) { |
1107 | node = nilfs_btree_get_nonroot_node(path, level); | 1192 | node = nilfs_btree_get_nonroot_node(path, level); |
1108 | nilfs_btree_node_delete(btree, node, keyp, ptrp, | 1193 | ncblk = nilfs_btree_nchildren_per_block(btree); |
1109 | path[level].bp_index); | 1194 | nilfs_btree_node_delete(node, path[level].bp_index, |
1195 | keyp, ptrp, ncblk); | ||
1110 | if (!buffer_dirty(path[level].bp_bh)) | 1196 | if (!buffer_dirty(path[level].bp_bh)) |
1111 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 1197 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
1112 | if (path[level].bp_index == 0) | 1198 | if (path[level].bp_index == 0) |
@@ -1114,17 +1200,18 @@ static void nilfs_btree_do_delete(struct nilfs_btree *btree, | |||
1114 | nilfs_btree_node_get_key(node, 0)); | 1200 | nilfs_btree_node_get_key(node, 0)); |
1115 | } else { | 1201 | } else { |
1116 | node = nilfs_btree_get_root(btree); | 1202 | node = nilfs_btree_get_root(btree); |
1117 | nilfs_btree_node_delete(btree, node, keyp, ptrp, | 1203 | nilfs_btree_node_delete(node, path[level].bp_index, |
1118 | path[level].bp_index); | 1204 | keyp, ptrp, |
1205 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
1119 | } | 1206 | } |
1120 | } | 1207 | } |
1121 | 1208 | ||
1122 | static void nilfs_btree_borrow_left(struct nilfs_btree *btree, | 1209 | static void nilfs_btree_borrow_left(struct nilfs_bmap *btree, |
1123 | struct nilfs_btree_path *path, | 1210 | struct nilfs_btree_path *path, |
1124 | int level, __u64 *keyp, __u64 *ptrp) | 1211 | int level, __u64 *keyp, __u64 *ptrp) |
1125 | { | 1212 | { |
1126 | struct nilfs_btree_node *node, *left; | 1213 | struct nilfs_btree_node *node, *left; |
1127 | int nchildren, lnchildren, n; | 1214 | int nchildren, lnchildren, n, ncblk; |
1128 | 1215 | ||
1129 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); | 1216 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); |
1130 | 1217 | ||
@@ -1132,10 +1219,11 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree, | |||
1132 | left = nilfs_btree_get_sib_node(path, level); | 1219 | left = nilfs_btree_get_sib_node(path, level); |
1133 | nchildren = nilfs_btree_node_get_nchildren(node); | 1220 | nchildren = nilfs_btree_node_get_nchildren(node); |
1134 | lnchildren = nilfs_btree_node_get_nchildren(left); | 1221 | lnchildren = nilfs_btree_node_get_nchildren(left); |
1222 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1135 | 1223 | ||
1136 | n = (nchildren + lnchildren) / 2 - nchildren; | 1224 | n = (nchildren + lnchildren) / 2 - nchildren; |
1137 | 1225 | ||
1138 | nilfs_btree_node_move_right(btree, left, node, n); | 1226 | nilfs_btree_node_move_right(left, node, n, ncblk, ncblk); |
1139 | 1227 | ||
1140 | if (!buffer_dirty(path[level].bp_bh)) | 1228 | if (!buffer_dirty(path[level].bp_bh)) |
1141 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 1229 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -1150,12 +1238,12 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree, | |||
1150 | path[level].bp_index += n; | 1238 | path[level].bp_index += n; |
1151 | } | 1239 | } |
1152 | 1240 | ||
1153 | static void nilfs_btree_borrow_right(struct nilfs_btree *btree, | 1241 | static void nilfs_btree_borrow_right(struct nilfs_bmap *btree, |
1154 | struct nilfs_btree_path *path, | 1242 | struct nilfs_btree_path *path, |
1155 | int level, __u64 *keyp, __u64 *ptrp) | 1243 | int level, __u64 *keyp, __u64 *ptrp) |
1156 | { | 1244 | { |
1157 | struct nilfs_btree_node *node, *right; | 1245 | struct nilfs_btree_node *node, *right; |
1158 | int nchildren, rnchildren, n; | 1246 | int nchildren, rnchildren, n, ncblk; |
1159 | 1247 | ||
1160 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); | 1248 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); |
1161 | 1249 | ||
@@ -1163,10 +1251,11 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree, | |||
1163 | right = nilfs_btree_get_sib_node(path, level); | 1251 | right = nilfs_btree_get_sib_node(path, level); |
1164 | nchildren = nilfs_btree_node_get_nchildren(node); | 1252 | nchildren = nilfs_btree_node_get_nchildren(node); |
1165 | rnchildren = nilfs_btree_node_get_nchildren(right); | 1253 | rnchildren = nilfs_btree_node_get_nchildren(right); |
1254 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1166 | 1255 | ||
1167 | n = (nchildren + rnchildren) / 2 - nchildren; | 1256 | n = (nchildren + rnchildren) / 2 - nchildren; |
1168 | 1257 | ||
1169 | nilfs_btree_node_move_left(btree, node, right, n); | 1258 | nilfs_btree_node_move_left(node, right, n, ncblk, ncblk); |
1170 | 1259 | ||
1171 | if (!buffer_dirty(path[level].bp_bh)) | 1260 | if (!buffer_dirty(path[level].bp_bh)) |
1172 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 1261 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -1182,21 +1271,22 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree, | |||
1182 | path[level].bp_sib_bh = NULL; | 1271 | path[level].bp_sib_bh = NULL; |
1183 | } | 1272 | } |
1184 | 1273 | ||
1185 | static void nilfs_btree_concat_left(struct nilfs_btree *btree, | 1274 | static void nilfs_btree_concat_left(struct nilfs_bmap *btree, |
1186 | struct nilfs_btree_path *path, | 1275 | struct nilfs_btree_path *path, |
1187 | int level, __u64 *keyp, __u64 *ptrp) | 1276 | int level, __u64 *keyp, __u64 *ptrp) |
1188 | { | 1277 | { |
1189 | struct nilfs_btree_node *node, *left; | 1278 | struct nilfs_btree_node *node, *left; |
1190 | int n; | 1279 | int n, ncblk; |
1191 | 1280 | ||
1192 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); | 1281 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); |
1193 | 1282 | ||
1194 | node = nilfs_btree_get_nonroot_node(path, level); | 1283 | node = nilfs_btree_get_nonroot_node(path, level); |
1195 | left = nilfs_btree_get_sib_node(path, level); | 1284 | left = nilfs_btree_get_sib_node(path, level); |
1285 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1196 | 1286 | ||
1197 | n = nilfs_btree_node_get_nchildren(node); | 1287 | n = nilfs_btree_node_get_nchildren(node); |
1198 | 1288 | ||
1199 | nilfs_btree_node_move_left(btree, left, node, n); | 1289 | nilfs_btree_node_move_left(left, node, n, ncblk, ncblk); |
1200 | 1290 | ||
1201 | if (!buffer_dirty(path[level].bp_sib_bh)) | 1291 | if (!buffer_dirty(path[level].bp_sib_bh)) |
1202 | nilfs_btnode_mark_dirty(path[level].bp_sib_bh); | 1292 | nilfs_btnode_mark_dirty(path[level].bp_sib_bh); |
@@ -1207,21 +1297,22 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree, | |||
1207 | path[level].bp_index += nilfs_btree_node_get_nchildren(left); | 1297 | path[level].bp_index += nilfs_btree_node_get_nchildren(left); |
1208 | } | 1298 | } |
1209 | 1299 | ||
1210 | static void nilfs_btree_concat_right(struct nilfs_btree *btree, | 1300 | static void nilfs_btree_concat_right(struct nilfs_bmap *btree, |
1211 | struct nilfs_btree_path *path, | 1301 | struct nilfs_btree_path *path, |
1212 | int level, __u64 *keyp, __u64 *ptrp) | 1302 | int level, __u64 *keyp, __u64 *ptrp) |
1213 | { | 1303 | { |
1214 | struct nilfs_btree_node *node, *right; | 1304 | struct nilfs_btree_node *node, *right; |
1215 | int n; | 1305 | int n, ncblk; |
1216 | 1306 | ||
1217 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); | 1307 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); |
1218 | 1308 | ||
1219 | node = nilfs_btree_get_nonroot_node(path, level); | 1309 | node = nilfs_btree_get_nonroot_node(path, level); |
1220 | right = nilfs_btree_get_sib_node(path, level); | 1310 | right = nilfs_btree_get_sib_node(path, level); |
1311 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1221 | 1312 | ||
1222 | n = nilfs_btree_node_get_nchildren(right); | 1313 | n = nilfs_btree_node_get_nchildren(right); |
1223 | 1314 | ||
1224 | nilfs_btree_node_move_left(btree, node, right, n); | 1315 | nilfs_btree_node_move_left(node, right, n, ncblk, ncblk); |
1225 | 1316 | ||
1226 | if (!buffer_dirty(path[level].bp_bh)) | 1317 | if (!buffer_dirty(path[level].bp_bh)) |
1227 | nilfs_btnode_mark_dirty(path[level].bp_bh); | 1318 | nilfs_btnode_mark_dirty(path[level].bp_bh); |
@@ -1231,29 +1322,32 @@ static void nilfs_btree_concat_right(struct nilfs_btree *btree, | |||
1231 | path[level + 1].bp_index++; | 1322 | path[level + 1].bp_index++; |
1232 | } | 1323 | } |
1233 | 1324 | ||
1234 | static void nilfs_btree_shrink(struct nilfs_btree *btree, | 1325 | static void nilfs_btree_shrink(struct nilfs_bmap *btree, |
1235 | struct nilfs_btree_path *path, | 1326 | struct nilfs_btree_path *path, |
1236 | int level, __u64 *keyp, __u64 *ptrp) | 1327 | int level, __u64 *keyp, __u64 *ptrp) |
1237 | { | 1328 | { |
1238 | struct nilfs_btree_node *root, *child; | 1329 | struct nilfs_btree_node *root, *child; |
1239 | int n; | 1330 | int n, ncblk; |
1240 | 1331 | ||
1241 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); | 1332 | nilfs_btree_do_delete(btree, path, level, keyp, ptrp); |
1242 | 1333 | ||
1243 | root = nilfs_btree_get_root(btree); | 1334 | root = nilfs_btree_get_root(btree); |
1244 | child = nilfs_btree_get_nonroot_node(path, level); | 1335 | child = nilfs_btree_get_nonroot_node(path, level); |
1336 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1245 | 1337 | ||
1246 | nilfs_btree_node_delete(btree, root, NULL, NULL, 0); | 1338 | nilfs_btree_node_delete(root, 0, NULL, NULL, |
1339 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
1247 | nilfs_btree_node_set_level(root, level); | 1340 | nilfs_btree_node_set_level(root, level); |
1248 | n = nilfs_btree_node_get_nchildren(child); | 1341 | n = nilfs_btree_node_get_nchildren(child); |
1249 | nilfs_btree_node_move_left(btree, root, child, n); | 1342 | nilfs_btree_node_move_left(root, child, n, |
1343 | NILFS_BTREE_ROOT_NCHILDREN_MAX, ncblk); | ||
1250 | 1344 | ||
1251 | nilfs_btnode_delete(path[level].bp_bh); | 1345 | nilfs_btnode_delete(path[level].bp_bh); |
1252 | path[level].bp_bh = NULL; | 1346 | path[level].bp_bh = NULL; |
1253 | } | 1347 | } |
1254 | 1348 | ||
1255 | 1349 | ||
1256 | static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | 1350 | static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, |
1257 | struct nilfs_btree_path *path, | 1351 | struct nilfs_btree_path *path, |
1258 | int *levelp, | 1352 | int *levelp, |
1259 | struct nilfs_bmap_stats *stats, | 1353 | struct nilfs_bmap_stats *stats, |
@@ -1262,42 +1356,43 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
1262 | struct buffer_head *bh; | 1356 | struct buffer_head *bh; |
1263 | struct nilfs_btree_node *node, *parent, *sib; | 1357 | struct nilfs_btree_node *node, *parent, *sib; |
1264 | __u64 sibptr; | 1358 | __u64 sibptr; |
1265 | int pindex, level, ret; | 1359 | int pindex, level, ncmin, ncmax, ncblk, ret; |
1266 | 1360 | ||
1267 | ret = 0; | 1361 | ret = 0; |
1268 | stats->bs_nblocks = 0; | 1362 | stats->bs_nblocks = 0; |
1363 | ncmin = NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree)); | ||
1364 | ncblk = nilfs_btree_nchildren_per_block(btree); | ||
1365 | |||
1269 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; | 1366 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; |
1270 | level < nilfs_btree_height(btree) - 1; | 1367 | level < nilfs_btree_height(btree) - 1; |
1271 | level++) { | 1368 | level++) { |
1272 | node = nilfs_btree_get_nonroot_node(path, level); | 1369 | node = nilfs_btree_get_nonroot_node(path, level); |
1273 | path[level].bp_oldreq.bpr_ptr = | 1370 | path[level].bp_oldreq.bpr_ptr = |
1274 | nilfs_btree_node_get_ptr(btree, node, | 1371 | nilfs_btree_node_get_ptr(node, path[level].bp_index, |
1275 | path[level].bp_index); | 1372 | ncblk); |
1276 | ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap, | 1373 | ret = nilfs_bmap_prepare_end_ptr(btree, |
1277 | &path[level].bp_oldreq, dat); | 1374 | &path[level].bp_oldreq, dat); |
1278 | if (ret < 0) | 1375 | if (ret < 0) |
1279 | goto err_out_child_node; | 1376 | goto err_out_child_node; |
1280 | 1377 | ||
1281 | if (nilfs_btree_node_get_nchildren(node) > | 1378 | if (nilfs_btree_node_get_nchildren(node) > ncmin) { |
1282 | nilfs_btree_node_nchildren_min(node, btree)) { | ||
1283 | path[level].bp_op = nilfs_btree_do_delete; | 1379 | path[level].bp_op = nilfs_btree_do_delete; |
1284 | stats->bs_nblocks++; | 1380 | stats->bs_nblocks++; |
1285 | goto out; | 1381 | goto out; |
1286 | } | 1382 | } |
1287 | 1383 | ||
1288 | parent = nilfs_btree_get_node(btree, path, level + 1); | 1384 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
1289 | pindex = path[level + 1].bp_index; | 1385 | pindex = path[level + 1].bp_index; |
1290 | 1386 | ||
1291 | if (pindex > 0) { | 1387 | if (pindex > 0) { |
1292 | /* left sibling */ | 1388 | /* left sibling */ |
1293 | sibptr = nilfs_btree_node_get_ptr(btree, parent, | 1389 | sibptr = nilfs_btree_node_get_ptr(parent, pindex - 1, |
1294 | pindex - 1); | 1390 | ncmax); |
1295 | ret = nilfs_btree_get_block(btree, sibptr, &bh); | 1391 | ret = nilfs_btree_get_block(btree, sibptr, &bh); |
1296 | if (ret < 0) | 1392 | if (ret < 0) |
1297 | goto err_out_curr_node; | 1393 | goto err_out_curr_node; |
1298 | sib = (struct nilfs_btree_node *)bh->b_data; | 1394 | sib = (struct nilfs_btree_node *)bh->b_data; |
1299 | if (nilfs_btree_node_get_nchildren(sib) > | 1395 | if (nilfs_btree_node_get_nchildren(sib) > ncmin) { |
1300 | nilfs_btree_node_nchildren_min(sib, btree)) { | ||
1301 | path[level].bp_sib_bh = bh; | 1396 | path[level].bp_sib_bh = bh; |
1302 | path[level].bp_op = nilfs_btree_borrow_left; | 1397 | path[level].bp_op = nilfs_btree_borrow_left; |
1303 | stats->bs_nblocks++; | 1398 | stats->bs_nblocks++; |
@@ -1311,14 +1406,13 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
1311 | } else if (pindex < | 1406 | } else if (pindex < |
1312 | nilfs_btree_node_get_nchildren(parent) - 1) { | 1407 | nilfs_btree_node_get_nchildren(parent) - 1) { |
1313 | /* right sibling */ | 1408 | /* right sibling */ |
1314 | sibptr = nilfs_btree_node_get_ptr(btree, parent, | 1409 | sibptr = nilfs_btree_node_get_ptr(parent, pindex + 1, |
1315 | pindex + 1); | 1410 | ncmax); |
1316 | ret = nilfs_btree_get_block(btree, sibptr, &bh); | 1411 | ret = nilfs_btree_get_block(btree, sibptr, &bh); |
1317 | if (ret < 0) | 1412 | if (ret < 0) |
1318 | goto err_out_curr_node; | 1413 | goto err_out_curr_node; |
1319 | sib = (struct nilfs_btree_node *)bh->b_data; | 1414 | sib = (struct nilfs_btree_node *)bh->b_data; |
1320 | if (nilfs_btree_node_get_nchildren(sib) > | 1415 | if (nilfs_btree_node_get_nchildren(sib) > ncmin) { |
1321 | nilfs_btree_node_nchildren_min(sib, btree)) { | ||
1322 | path[level].bp_sib_bh = bh; | 1416 | path[level].bp_sib_bh = bh; |
1323 | path[level].bp_op = nilfs_btree_borrow_right; | 1417 | path[level].bp_op = nilfs_btree_borrow_right; |
1324 | stats->bs_nblocks++; | 1418 | stats->bs_nblocks++; |
@@ -1349,10 +1443,10 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
1349 | 1443 | ||
1350 | node = nilfs_btree_get_root(btree); | 1444 | node = nilfs_btree_get_root(btree); |
1351 | path[level].bp_oldreq.bpr_ptr = | 1445 | path[level].bp_oldreq.bpr_ptr = |
1352 | nilfs_btree_node_get_ptr(btree, node, path[level].bp_index); | 1446 | nilfs_btree_node_get_ptr(node, path[level].bp_index, |
1447 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
1353 | 1448 | ||
1354 | ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap, | 1449 | ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat); |
1355 | &path[level].bp_oldreq, dat); | ||
1356 | if (ret < 0) | 1450 | if (ret < 0) |
1357 | goto err_out_child_node; | 1451 | goto err_out_child_node; |
1358 | 1452 | ||
@@ -1367,75 +1461,68 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree, | |||
1367 | 1461 | ||
1368 | /* error */ | 1462 | /* error */ |
1369 | err_out_curr_node: | 1463 | err_out_curr_node: |
1370 | nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq, dat); | 1464 | nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat); |
1371 | err_out_child_node: | 1465 | err_out_child_node: |
1372 | for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) { | 1466 | for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) { |
1373 | brelse(path[level].bp_sib_bh); | 1467 | brelse(path[level].bp_sib_bh); |
1374 | nilfs_bmap_abort_end_ptr(&btree->bt_bmap, | 1468 | nilfs_bmap_abort_end_ptr(btree, &path[level].bp_oldreq, dat); |
1375 | &path[level].bp_oldreq, dat); | ||
1376 | } | 1469 | } |
1377 | *levelp = level; | 1470 | *levelp = level; |
1378 | stats->bs_nblocks = 0; | 1471 | stats->bs_nblocks = 0; |
1379 | return ret; | 1472 | return ret; |
1380 | } | 1473 | } |
1381 | 1474 | ||
1382 | static void nilfs_btree_commit_delete(struct nilfs_btree *btree, | 1475 | static void nilfs_btree_commit_delete(struct nilfs_bmap *btree, |
1383 | struct nilfs_btree_path *path, | 1476 | struct nilfs_btree_path *path, |
1384 | int maxlevel, struct inode *dat) | 1477 | int maxlevel, struct inode *dat) |
1385 | { | 1478 | { |
1386 | int level; | 1479 | int level; |
1387 | 1480 | ||
1388 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { | 1481 | for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { |
1389 | nilfs_bmap_commit_end_ptr(&btree->bt_bmap, | 1482 | nilfs_bmap_commit_end_ptr(btree, &path[level].bp_oldreq, dat); |
1390 | &path[level].bp_oldreq, dat); | ||
1391 | path[level].bp_op(btree, path, level, NULL, NULL); | 1483 | path[level].bp_op(btree, path, level, NULL, NULL); |
1392 | } | 1484 | } |
1393 | 1485 | ||
1394 | if (!nilfs_bmap_dirty(&btree->bt_bmap)) | 1486 | if (!nilfs_bmap_dirty(btree)) |
1395 | nilfs_bmap_set_dirty(&btree->bt_bmap); | 1487 | nilfs_bmap_set_dirty(btree); |
1396 | } | 1488 | } |
1397 | 1489 | ||
1398 | static int nilfs_btree_delete(struct nilfs_bmap *bmap, __u64 key) | 1490 | static int nilfs_btree_delete(struct nilfs_bmap *btree, __u64 key) |
1399 | 1491 | ||
1400 | { | 1492 | { |
1401 | struct nilfs_btree *btree; | ||
1402 | struct nilfs_btree_path *path; | 1493 | struct nilfs_btree_path *path; |
1403 | struct nilfs_bmap_stats stats; | 1494 | struct nilfs_bmap_stats stats; |
1404 | struct inode *dat; | 1495 | struct inode *dat; |
1405 | int level, ret; | 1496 | int level, ret; |
1406 | 1497 | ||
1407 | btree = (struct nilfs_btree *)bmap; | ||
1408 | path = nilfs_btree_alloc_path(); | 1498 | path = nilfs_btree_alloc_path(); |
1409 | if (path == NULL) | 1499 | if (path == NULL) |
1410 | return -ENOMEM; | 1500 | return -ENOMEM; |
1411 | 1501 | ||
1412 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, | 1502 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, |
1413 | NILFS_BTREE_LEVEL_NODE_MIN); | 1503 | NILFS_BTREE_LEVEL_NODE_MIN, 0); |
1414 | if (ret < 0) | 1504 | if (ret < 0) |
1415 | goto out; | 1505 | goto out; |
1416 | 1506 | ||
1417 | 1507 | ||
1418 | dat = NILFS_BMAP_USE_VBN(&btree->bt_bmap) ? | 1508 | dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; |
1419 | nilfs_bmap_get_dat(&btree->bt_bmap) : NULL; | ||
1420 | 1509 | ||
1421 | ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat); | 1510 | ret = nilfs_btree_prepare_delete(btree, path, &level, &stats, dat); |
1422 | if (ret < 0) | 1511 | if (ret < 0) |
1423 | goto out; | 1512 | goto out; |
1424 | nilfs_btree_commit_delete(btree, path, level, dat); | 1513 | nilfs_btree_commit_delete(btree, path, level, dat); |
1425 | nilfs_bmap_sub_blocks(bmap, stats.bs_nblocks); | 1514 | nilfs_bmap_sub_blocks(btree, stats.bs_nblocks); |
1426 | 1515 | ||
1427 | out: | 1516 | out: |
1428 | nilfs_btree_free_path(path); | 1517 | nilfs_btree_free_path(path); |
1429 | return ret; | 1518 | return ret; |
1430 | } | 1519 | } |
1431 | 1520 | ||
1432 | static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) | 1521 | static int nilfs_btree_last_key(const struct nilfs_bmap *btree, __u64 *keyp) |
1433 | { | 1522 | { |
1434 | struct nilfs_btree *btree; | ||
1435 | struct nilfs_btree_path *path; | 1523 | struct nilfs_btree_path *path; |
1436 | int ret; | 1524 | int ret; |
1437 | 1525 | ||
1438 | btree = (struct nilfs_btree *)bmap; | ||
1439 | path = nilfs_btree_alloc_path(); | 1526 | path = nilfs_btree_alloc_path(); |
1440 | if (path == NULL) | 1527 | if (path == NULL) |
1441 | return -ENOMEM; | 1528 | return -ENOMEM; |
@@ -1447,16 +1534,14 @@ static int nilfs_btree_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) | |||
1447 | return ret; | 1534 | return ret; |
1448 | } | 1535 | } |
1449 | 1536 | ||
1450 | static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key) | 1537 | static int nilfs_btree_check_delete(struct nilfs_bmap *btree, __u64 key) |
1451 | { | 1538 | { |
1452 | struct buffer_head *bh; | 1539 | struct buffer_head *bh; |
1453 | struct nilfs_btree *btree; | ||
1454 | struct nilfs_btree_node *root, *node; | 1540 | struct nilfs_btree_node *root, *node; |
1455 | __u64 maxkey, nextmaxkey; | 1541 | __u64 maxkey, nextmaxkey; |
1456 | __u64 ptr; | 1542 | __u64 ptr; |
1457 | int nchildren, ret; | 1543 | int nchildren, ret; |
1458 | 1544 | ||
1459 | btree = (struct nilfs_btree *)bmap; | ||
1460 | root = nilfs_btree_get_root(btree); | 1545 | root = nilfs_btree_get_root(btree); |
1461 | switch (nilfs_btree_height(btree)) { | 1546 | switch (nilfs_btree_height(btree)) { |
1462 | case 2: | 1547 | case 2: |
@@ -1467,7 +1552,8 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key) | |||
1467 | nchildren = nilfs_btree_node_get_nchildren(root); | 1552 | nchildren = nilfs_btree_node_get_nchildren(root); |
1468 | if (nchildren > 1) | 1553 | if (nchildren > 1) |
1469 | return 0; | 1554 | return 0; |
1470 | ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); | 1555 | ptr = nilfs_btree_node_get_ptr(root, nchildren - 1, |
1556 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
1471 | ret = nilfs_btree_get_block(btree, ptr, &bh); | 1557 | ret = nilfs_btree_get_block(btree, ptr, &bh); |
1472 | if (ret < 0) | 1558 | if (ret < 0) |
1473 | return ret; | 1559 | return ret; |
@@ -1487,32 +1573,33 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key) | |||
1487 | return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW); | 1573 | return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW); |
1488 | } | 1574 | } |
1489 | 1575 | ||
1490 | static int nilfs_btree_gather_data(struct nilfs_bmap *bmap, | 1576 | static int nilfs_btree_gather_data(struct nilfs_bmap *btree, |
1491 | __u64 *keys, __u64 *ptrs, int nitems) | 1577 | __u64 *keys, __u64 *ptrs, int nitems) |
1492 | { | 1578 | { |
1493 | struct buffer_head *bh; | 1579 | struct buffer_head *bh; |
1494 | struct nilfs_btree *btree; | ||
1495 | struct nilfs_btree_node *node, *root; | 1580 | struct nilfs_btree_node *node, *root; |
1496 | __le64 *dkeys; | 1581 | __le64 *dkeys; |
1497 | __le64 *dptrs; | 1582 | __le64 *dptrs; |
1498 | __u64 ptr; | 1583 | __u64 ptr; |
1499 | int nchildren, i, ret; | 1584 | int nchildren, ncmax, i, ret; |
1500 | 1585 | ||
1501 | btree = (struct nilfs_btree *)bmap; | ||
1502 | root = nilfs_btree_get_root(btree); | 1586 | root = nilfs_btree_get_root(btree); |
1503 | switch (nilfs_btree_height(btree)) { | 1587 | switch (nilfs_btree_height(btree)) { |
1504 | case 2: | 1588 | case 2: |
1505 | bh = NULL; | 1589 | bh = NULL; |
1506 | node = root; | 1590 | node = root; |
1591 | ncmax = NILFS_BTREE_ROOT_NCHILDREN_MAX; | ||
1507 | break; | 1592 | break; |
1508 | case 3: | 1593 | case 3: |
1509 | nchildren = nilfs_btree_node_get_nchildren(root); | 1594 | nchildren = nilfs_btree_node_get_nchildren(root); |
1510 | WARN_ON(nchildren > 1); | 1595 | WARN_ON(nchildren > 1); |
1511 | ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); | 1596 | ptr = nilfs_btree_node_get_ptr(root, nchildren - 1, |
1597 | NILFS_BTREE_ROOT_NCHILDREN_MAX); | ||
1512 | ret = nilfs_btree_get_block(btree, ptr, &bh); | 1598 | ret = nilfs_btree_get_block(btree, ptr, &bh); |
1513 | if (ret < 0) | 1599 | if (ret < 0) |
1514 | return ret; | 1600 | return ret; |
1515 | node = (struct nilfs_btree_node *)bh->b_data; | 1601 | node = (struct nilfs_btree_node *)bh->b_data; |
1602 | ncmax = nilfs_btree_nchildren_per_block(btree); | ||
1516 | break; | 1603 | break; |
1517 | default: | 1604 | default: |
1518 | node = NULL; | 1605 | node = NULL; |
@@ -1523,10 +1610,10 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap, | |||
1523 | if (nchildren < nitems) | 1610 | if (nchildren < nitems) |
1524 | nitems = nchildren; | 1611 | nitems = nchildren; |
1525 | dkeys = nilfs_btree_node_dkeys(node); | 1612 | dkeys = nilfs_btree_node_dkeys(node); |
1526 | dptrs = nilfs_btree_node_dptrs(node, btree); | 1613 | dptrs = nilfs_btree_node_dptrs(node, ncmax); |
1527 | for (i = 0; i < nitems; i++) { | 1614 | for (i = 0; i < nitems; i++) { |
1528 | keys[i] = nilfs_bmap_dkey_to_key(dkeys[i]); | 1615 | keys[i] = le64_to_cpu(dkeys[i]); |
1529 | ptrs[i] = nilfs_bmap_dptr_to_ptr(dptrs[i]); | 1616 | ptrs[i] = le64_to_cpu(dptrs[i]); |
1530 | } | 1617 | } |
1531 | 1618 | ||
1532 | if (bh != NULL) | 1619 | if (bh != NULL) |
@@ -1536,14 +1623,13 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap, | |||
1536 | } | 1623 | } |
1537 | 1624 | ||
1538 | static int | 1625 | static int |
1539 | nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, | 1626 | nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *btree, __u64 key, |
1540 | union nilfs_bmap_ptr_req *dreq, | 1627 | union nilfs_bmap_ptr_req *dreq, |
1541 | union nilfs_bmap_ptr_req *nreq, | 1628 | union nilfs_bmap_ptr_req *nreq, |
1542 | struct buffer_head **bhp, | 1629 | struct buffer_head **bhp, |
1543 | struct nilfs_bmap_stats *stats) | 1630 | struct nilfs_bmap_stats *stats) |
1544 | { | 1631 | { |
1545 | struct buffer_head *bh; | 1632 | struct buffer_head *bh; |
1546 | struct nilfs_btree *btree = (struct nilfs_btree *)bmap; | ||
1547 | struct inode *dat = NULL; | 1633 | struct inode *dat = NULL; |
1548 | int ret; | 1634 | int ret; |
1549 | 1635 | ||
@@ -1551,12 +1637,12 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, | |||
1551 | 1637 | ||
1552 | /* for data */ | 1638 | /* for data */ |
1553 | /* cannot find near ptr */ | 1639 | /* cannot find near ptr */ |
1554 | if (NILFS_BMAP_USE_VBN(bmap)) { | 1640 | if (NILFS_BMAP_USE_VBN(btree)) { |
1555 | dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key); | 1641 | dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key); |
1556 | dat = nilfs_bmap_get_dat(bmap); | 1642 | dat = nilfs_bmap_get_dat(btree); |
1557 | } | 1643 | } |
1558 | 1644 | ||
1559 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq, dat); | 1645 | ret = nilfs_bmap_prepare_alloc_ptr(btree, dreq, dat); |
1560 | if (ret < 0) | 1646 | if (ret < 0) |
1561 | return ret; | 1647 | return ret; |
1562 | 1648 | ||
@@ -1564,7 +1650,7 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, | |||
1564 | stats->bs_nblocks++; | 1650 | stats->bs_nblocks++; |
1565 | if (nreq != NULL) { | 1651 | if (nreq != NULL) { |
1566 | nreq->bpr_ptr = dreq->bpr_ptr + 1; | 1652 | nreq->bpr_ptr = dreq->bpr_ptr + 1; |
1567 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq, dat); | 1653 | ret = nilfs_bmap_prepare_alloc_ptr(btree, nreq, dat); |
1568 | if (ret < 0) | 1654 | if (ret < 0) |
1569 | goto err_out_dreq; | 1655 | goto err_out_dreq; |
1570 | 1656 | ||
@@ -1581,16 +1667,16 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key, | |||
1581 | 1667 | ||
1582 | /* error */ | 1668 | /* error */ |
1583 | err_out_nreq: | 1669 | err_out_nreq: |
1584 | nilfs_bmap_abort_alloc_ptr(bmap, nreq, dat); | 1670 | nilfs_bmap_abort_alloc_ptr(btree, nreq, dat); |
1585 | err_out_dreq: | 1671 | err_out_dreq: |
1586 | nilfs_bmap_abort_alloc_ptr(bmap, dreq, dat); | 1672 | nilfs_bmap_abort_alloc_ptr(btree, dreq, dat); |
1587 | stats->bs_nblocks = 0; | 1673 | stats->bs_nblocks = 0; |
1588 | return ret; | 1674 | return ret; |
1589 | 1675 | ||
1590 | } | 1676 | } |
1591 | 1677 | ||
1592 | static void | 1678 | static void |
1593 | nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, | 1679 | nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *btree, |
1594 | __u64 key, __u64 ptr, | 1680 | __u64 key, __u64 ptr, |
1595 | const __u64 *keys, const __u64 *ptrs, | 1681 | const __u64 *keys, const __u64 *ptrs, |
1596 | int n, | 1682 | int n, |
@@ -1598,57 +1684,59 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, | |||
1598 | union nilfs_bmap_ptr_req *nreq, | 1684 | union nilfs_bmap_ptr_req *nreq, |
1599 | struct buffer_head *bh) | 1685 | struct buffer_head *bh) |
1600 | { | 1686 | { |
1601 | struct nilfs_btree *btree = (struct nilfs_btree *)bmap; | ||
1602 | struct nilfs_btree_node *node; | 1687 | struct nilfs_btree_node *node; |
1603 | struct inode *dat; | 1688 | struct inode *dat; |
1604 | __u64 tmpptr; | 1689 | __u64 tmpptr; |
1690 | int ncblk; | ||
1605 | 1691 | ||
1606 | /* free resources */ | 1692 | /* free resources */ |
1607 | if (bmap->b_ops->bop_clear != NULL) | 1693 | if (btree->b_ops->bop_clear != NULL) |
1608 | bmap->b_ops->bop_clear(bmap); | 1694 | btree->b_ops->bop_clear(btree); |
1609 | 1695 | ||
1610 | /* ptr must be a pointer to a buffer head. */ | 1696 | /* ptr must be a pointer to a buffer head. */ |
1611 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); | 1697 | set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); |
1612 | 1698 | ||
1613 | /* convert and insert */ | 1699 | /* convert and insert */ |
1614 | dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL; | 1700 | dat = NILFS_BMAP_USE_VBN(btree) ? nilfs_bmap_get_dat(btree) : NULL; |
1615 | nilfs_btree_init(bmap); | 1701 | nilfs_btree_init(btree); |
1616 | if (nreq != NULL) { | 1702 | if (nreq != NULL) { |
1617 | nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat); | 1703 | nilfs_bmap_commit_alloc_ptr(btree, dreq, dat); |
1618 | nilfs_bmap_commit_alloc_ptr(bmap, nreq, dat); | 1704 | nilfs_bmap_commit_alloc_ptr(btree, nreq, dat); |
1619 | 1705 | ||
1620 | /* create child node at level 1 */ | 1706 | /* create child node at level 1 */ |
1621 | node = (struct nilfs_btree_node *)bh->b_data; | 1707 | node = (struct nilfs_btree_node *)bh->b_data; |
1622 | nilfs_btree_node_init(btree, node, 0, 1, n, keys, ptrs); | 1708 | ncblk = nilfs_btree_nchildren_per_block(btree); |
1623 | nilfs_btree_node_insert(btree, node, | 1709 | nilfs_btree_node_init(node, 0, 1, n, ncblk, keys, ptrs); |
1624 | key, dreq->bpr_ptr, n); | 1710 | nilfs_btree_node_insert(node, n, key, dreq->bpr_ptr, ncblk); |
1625 | if (!buffer_dirty(bh)) | 1711 | if (!buffer_dirty(bh)) |
1626 | nilfs_btnode_mark_dirty(bh); | 1712 | nilfs_btnode_mark_dirty(bh); |
1627 | if (!nilfs_bmap_dirty(bmap)) | 1713 | if (!nilfs_bmap_dirty(btree)) |
1628 | nilfs_bmap_set_dirty(bmap); | 1714 | nilfs_bmap_set_dirty(btree); |
1629 | 1715 | ||
1630 | brelse(bh); | 1716 | brelse(bh); |
1631 | 1717 | ||
1632 | /* create root node at level 2 */ | 1718 | /* create root node at level 2 */ |
1633 | node = nilfs_btree_get_root(btree); | 1719 | node = nilfs_btree_get_root(btree); |
1634 | tmpptr = nreq->bpr_ptr; | 1720 | tmpptr = nreq->bpr_ptr; |
1635 | nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT, | 1721 | nilfs_btree_node_init(node, NILFS_BTREE_NODE_ROOT, 2, 1, |
1636 | 2, 1, &keys[0], &tmpptr); | 1722 | NILFS_BTREE_ROOT_NCHILDREN_MAX, |
1723 | &keys[0], &tmpptr); | ||
1637 | } else { | 1724 | } else { |
1638 | nilfs_bmap_commit_alloc_ptr(bmap, dreq, dat); | 1725 | nilfs_bmap_commit_alloc_ptr(btree, dreq, dat); |
1639 | 1726 | ||
1640 | /* create root node at level 1 */ | 1727 | /* create root node at level 1 */ |
1641 | node = nilfs_btree_get_root(btree); | 1728 | node = nilfs_btree_get_root(btree); |
1642 | nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT, | 1729 | nilfs_btree_node_init(node, NILFS_BTREE_NODE_ROOT, 1, n, |
1643 | 1, n, keys, ptrs); | 1730 | NILFS_BTREE_ROOT_NCHILDREN_MAX, |
1644 | nilfs_btree_node_insert(btree, node, | 1731 | keys, ptrs); |
1645 | key, dreq->bpr_ptr, n); | 1732 | nilfs_btree_node_insert(node, n, key, dreq->bpr_ptr, |
1646 | if (!nilfs_bmap_dirty(bmap)) | 1733 | NILFS_BTREE_ROOT_NCHILDREN_MAX); |
1647 | nilfs_bmap_set_dirty(bmap); | 1734 | if (!nilfs_bmap_dirty(btree)) |
1735 | nilfs_bmap_set_dirty(btree); | ||
1648 | } | 1736 | } |
1649 | 1737 | ||
1650 | if (NILFS_BMAP_USE_VBN(bmap)) | 1738 | if (NILFS_BMAP_USE_VBN(btree)) |
1651 | nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr); | 1739 | nilfs_bmap_set_target_v(btree, key, dreq->bpr_ptr); |
1652 | } | 1740 | } |
1653 | 1741 | ||
1654 | /** | 1742 | /** |
@@ -1660,7 +1748,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, | |||
1660 | * @ptrs: | 1748 | * @ptrs: |
1661 | * @n: | 1749 | * @n: |
1662 | */ | 1750 | */ |
1663 | int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap, | 1751 | int nilfs_btree_convert_and_insert(struct nilfs_bmap *btree, |
1664 | __u64 key, __u64 ptr, | 1752 | __u64 key, __u64 ptr, |
1665 | const __u64 *keys, const __u64 *ptrs, int n) | 1753 | const __u64 *keys, const __u64 *ptrs, int n) |
1666 | { | 1754 | { |
@@ -1673,7 +1761,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap, | |||
1673 | di = &dreq; | 1761 | di = &dreq; |
1674 | ni = NULL; | 1762 | ni = NULL; |
1675 | } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX( | 1763 | } else if ((n + 1) <= NILFS_BTREE_NODE_NCHILDREN_MAX( |
1676 | 1 << bmap->b_inode->i_blkbits)) { | 1764 | 1 << btree->b_inode->i_blkbits)) { |
1677 | di = &dreq; | 1765 | di = &dreq; |
1678 | ni = &nreq; | 1766 | ni = &nreq; |
1679 | } else { | 1767 | } else { |
@@ -1682,17 +1770,17 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap, | |||
1682 | BUG(); | 1770 | BUG(); |
1683 | } | 1771 | } |
1684 | 1772 | ||
1685 | ret = nilfs_btree_prepare_convert_and_insert(bmap, key, di, ni, &bh, | 1773 | ret = nilfs_btree_prepare_convert_and_insert(btree, key, di, ni, &bh, |
1686 | &stats); | 1774 | &stats); |
1687 | if (ret < 0) | 1775 | if (ret < 0) |
1688 | return ret; | 1776 | return ret; |
1689 | nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n, | 1777 | nilfs_btree_commit_convert_and_insert(btree, key, ptr, keys, ptrs, n, |
1690 | di, ni, bh); | 1778 | di, ni, bh); |
1691 | nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); | 1779 | nilfs_bmap_add_blocks(btree, stats.bs_nblocks); |
1692 | return 0; | 1780 | return 0; |
1693 | } | 1781 | } |
1694 | 1782 | ||
1695 | static int nilfs_btree_propagate_p(struct nilfs_btree *btree, | 1783 | static int nilfs_btree_propagate_p(struct nilfs_bmap *btree, |
1696 | struct nilfs_btree_path *path, | 1784 | struct nilfs_btree_path *path, |
1697 | int level, | 1785 | int level, |
1698 | struct buffer_head *bh) | 1786 | struct buffer_head *bh) |
@@ -1704,17 +1792,17 @@ static int nilfs_btree_propagate_p(struct nilfs_btree *btree, | |||
1704 | return 0; | 1792 | return 0; |
1705 | } | 1793 | } |
1706 | 1794 | ||
1707 | static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, | 1795 | static int nilfs_btree_prepare_update_v(struct nilfs_bmap *btree, |
1708 | struct nilfs_btree_path *path, | 1796 | struct nilfs_btree_path *path, |
1709 | int level, struct inode *dat) | 1797 | int level, struct inode *dat) |
1710 | { | 1798 | { |
1711 | struct nilfs_btree_node *parent; | 1799 | struct nilfs_btree_node *parent; |
1712 | int ret; | 1800 | int ncmax, ret; |
1713 | 1801 | ||
1714 | parent = nilfs_btree_get_node(btree, path, level + 1); | 1802 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
1715 | path[level].bp_oldreq.bpr_ptr = | 1803 | path[level].bp_oldreq.bpr_ptr = |
1716 | nilfs_btree_node_get_ptr(btree, parent, | 1804 | nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index, |
1717 | path[level + 1].bp_index); | 1805 | ncmax); |
1718 | path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1; | 1806 | path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1; |
1719 | ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req, | 1807 | ret = nilfs_dat_prepare_update(dat, &path[level].bp_oldreq.bpr_req, |
1720 | &path[level].bp_newreq.bpr_req); | 1808 | &path[level].bp_newreq.bpr_req); |
@@ -1726,7 +1814,7 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, | |||
1726 | path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr; | 1814 | path[level].bp_ctxt.newkey = path[level].bp_newreq.bpr_ptr; |
1727 | path[level].bp_ctxt.bh = path[level].bp_bh; | 1815 | path[level].bp_ctxt.bh = path[level].bp_bh; |
1728 | ret = nilfs_btnode_prepare_change_key( | 1816 | ret = nilfs_btnode_prepare_change_key( |
1729 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 1817 | &NILFS_BMAP_I(btree)->i_btnode_cache, |
1730 | &path[level].bp_ctxt); | 1818 | &path[level].bp_ctxt); |
1731 | if (ret < 0) { | 1819 | if (ret < 0) { |
1732 | nilfs_dat_abort_update(dat, | 1820 | nilfs_dat_abort_update(dat, |
@@ -1739,30 +1827,31 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree, | |||
1739 | return 0; | 1827 | return 0; |
1740 | } | 1828 | } |
1741 | 1829 | ||
1742 | static void nilfs_btree_commit_update_v(struct nilfs_btree *btree, | 1830 | static void nilfs_btree_commit_update_v(struct nilfs_bmap *btree, |
1743 | struct nilfs_btree_path *path, | 1831 | struct nilfs_btree_path *path, |
1744 | int level, struct inode *dat) | 1832 | int level, struct inode *dat) |
1745 | { | 1833 | { |
1746 | struct nilfs_btree_node *parent; | 1834 | struct nilfs_btree_node *parent; |
1835 | int ncmax; | ||
1747 | 1836 | ||
1748 | nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req, | 1837 | nilfs_dat_commit_update(dat, &path[level].bp_oldreq.bpr_req, |
1749 | &path[level].bp_newreq.bpr_req, | 1838 | &path[level].bp_newreq.bpr_req, |
1750 | btree->bt_bmap.b_ptr_type == NILFS_BMAP_PTR_VS); | 1839 | btree->b_ptr_type == NILFS_BMAP_PTR_VS); |
1751 | 1840 | ||
1752 | if (buffer_nilfs_node(path[level].bp_bh)) { | 1841 | if (buffer_nilfs_node(path[level].bp_bh)) { |
1753 | nilfs_btnode_commit_change_key( | 1842 | nilfs_btnode_commit_change_key( |
1754 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 1843 | &NILFS_BMAP_I(btree)->i_btnode_cache, |
1755 | &path[level].bp_ctxt); | 1844 | &path[level].bp_ctxt); |
1756 | path[level].bp_bh = path[level].bp_ctxt.bh; | 1845 | path[level].bp_bh = path[level].bp_ctxt.bh; |
1757 | } | 1846 | } |
1758 | set_buffer_nilfs_volatile(path[level].bp_bh); | 1847 | set_buffer_nilfs_volatile(path[level].bp_bh); |
1759 | 1848 | ||
1760 | parent = nilfs_btree_get_node(btree, path, level + 1); | 1849 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
1761 | nilfs_btree_node_set_ptr(btree, parent, path[level + 1].bp_index, | 1850 | nilfs_btree_node_set_ptr(parent, path[level + 1].bp_index, |
1762 | path[level].bp_newreq.bpr_ptr); | 1851 | path[level].bp_newreq.bpr_ptr, ncmax); |
1763 | } | 1852 | } |
1764 | 1853 | ||
1765 | static void nilfs_btree_abort_update_v(struct nilfs_btree *btree, | 1854 | static void nilfs_btree_abort_update_v(struct nilfs_bmap *btree, |
1766 | struct nilfs_btree_path *path, | 1855 | struct nilfs_btree_path *path, |
1767 | int level, struct inode *dat) | 1856 | int level, struct inode *dat) |
1768 | { | 1857 | { |
@@ -1770,11 +1859,11 @@ static void nilfs_btree_abort_update_v(struct nilfs_btree *btree, | |||
1770 | &path[level].bp_newreq.bpr_req); | 1859 | &path[level].bp_newreq.bpr_req); |
1771 | if (buffer_nilfs_node(path[level].bp_bh)) | 1860 | if (buffer_nilfs_node(path[level].bp_bh)) |
1772 | nilfs_btnode_abort_change_key( | 1861 | nilfs_btnode_abort_change_key( |
1773 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 1862 | &NILFS_BMAP_I(btree)->i_btnode_cache, |
1774 | &path[level].bp_ctxt); | 1863 | &path[level].bp_ctxt); |
1775 | } | 1864 | } |
1776 | 1865 | ||
1777 | static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree, | 1866 | static int nilfs_btree_prepare_propagate_v(struct nilfs_bmap *btree, |
1778 | struct nilfs_btree_path *path, | 1867 | struct nilfs_btree_path *path, |
1779 | int minlevel, int *maxlevelp, | 1868 | int minlevel, int *maxlevelp, |
1780 | struct inode *dat) | 1869 | struct inode *dat) |
@@ -1809,7 +1898,7 @@ static int nilfs_btree_prepare_propagate_v(struct nilfs_btree *btree, | |||
1809 | return ret; | 1898 | return ret; |
1810 | } | 1899 | } |
1811 | 1900 | ||
1812 | static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree, | 1901 | static void nilfs_btree_commit_propagate_v(struct nilfs_bmap *btree, |
1813 | struct nilfs_btree_path *path, | 1902 | struct nilfs_btree_path *path, |
1814 | int minlevel, int maxlevel, | 1903 | int minlevel, int maxlevel, |
1815 | struct buffer_head *bh, | 1904 | struct buffer_head *bh, |
@@ -1824,14 +1913,15 @@ static void nilfs_btree_commit_propagate_v(struct nilfs_btree *btree, | |||
1824 | nilfs_btree_commit_update_v(btree, path, level, dat); | 1913 | nilfs_btree_commit_update_v(btree, path, level, dat); |
1825 | } | 1914 | } |
1826 | 1915 | ||
1827 | static int nilfs_btree_propagate_v(struct nilfs_btree *btree, | 1916 | static int nilfs_btree_propagate_v(struct nilfs_bmap *btree, |
1828 | struct nilfs_btree_path *path, | 1917 | struct nilfs_btree_path *path, |
1829 | int level, struct buffer_head *bh) | 1918 | int level, struct buffer_head *bh) |
1830 | { | 1919 | { |
1831 | int maxlevel = 0, ret; | 1920 | int maxlevel = 0, ret; |
1832 | struct nilfs_btree_node *parent; | 1921 | struct nilfs_btree_node *parent; |
1833 | struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap); | 1922 | struct inode *dat = nilfs_bmap_get_dat(btree); |
1834 | __u64 ptr; | 1923 | __u64 ptr; |
1924 | int ncmax; | ||
1835 | 1925 | ||
1836 | get_bh(bh); | 1926 | get_bh(bh); |
1837 | path[level].bp_bh = bh; | 1927 | path[level].bp_bh = bh; |
@@ -1841,9 +1931,10 @@ static int nilfs_btree_propagate_v(struct nilfs_btree *btree, | |||
1841 | goto out; | 1931 | goto out; |
1842 | 1932 | ||
1843 | if (buffer_nilfs_volatile(path[level].bp_bh)) { | 1933 | if (buffer_nilfs_volatile(path[level].bp_bh)) { |
1844 | parent = nilfs_btree_get_node(btree, path, level + 1); | 1934 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
1845 | ptr = nilfs_btree_node_get_ptr(btree, parent, | 1935 | ptr = nilfs_btree_node_get_ptr(parent, |
1846 | path[level + 1].bp_index); | 1936 | path[level + 1].bp_index, |
1937 | ncmax); | ||
1847 | ret = nilfs_dat_mark_dirty(dat, ptr); | 1938 | ret = nilfs_dat_mark_dirty(dat, ptr); |
1848 | if (ret < 0) | 1939 | if (ret < 0) |
1849 | goto out; | 1940 | goto out; |
@@ -1857,10 +1948,9 @@ static int nilfs_btree_propagate_v(struct nilfs_btree *btree, | |||
1857 | return ret; | 1948 | return ret; |
1858 | } | 1949 | } |
1859 | 1950 | ||
1860 | static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | 1951 | static int nilfs_btree_propagate(struct nilfs_bmap *btree, |
1861 | struct buffer_head *bh) | 1952 | struct buffer_head *bh) |
1862 | { | 1953 | { |
1863 | struct nilfs_btree *btree; | ||
1864 | struct nilfs_btree_path *path; | 1954 | struct nilfs_btree_path *path; |
1865 | struct nilfs_btree_node *node; | 1955 | struct nilfs_btree_node *node; |
1866 | __u64 key; | 1956 | __u64 key; |
@@ -1868,7 +1958,6 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
1868 | 1958 | ||
1869 | WARN_ON(!buffer_dirty(bh)); | 1959 | WARN_ON(!buffer_dirty(bh)); |
1870 | 1960 | ||
1871 | btree = (struct nilfs_btree *)bmap; | ||
1872 | path = nilfs_btree_alloc_path(); | 1961 | path = nilfs_btree_alloc_path(); |
1873 | if (path == NULL) | 1962 | if (path == NULL) |
1874 | return -ENOMEM; | 1963 | return -ENOMEM; |
@@ -1878,11 +1967,11 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
1878 | key = nilfs_btree_node_get_key(node, 0); | 1967 | key = nilfs_btree_node_get_key(node, 0); |
1879 | level = nilfs_btree_node_get_level(node); | 1968 | level = nilfs_btree_node_get_level(node); |
1880 | } else { | 1969 | } else { |
1881 | key = nilfs_bmap_data_get_key(bmap, bh); | 1970 | key = nilfs_bmap_data_get_key(btree, bh); |
1882 | level = NILFS_BTREE_LEVEL_DATA; | 1971 | level = NILFS_BTREE_LEVEL_DATA; |
1883 | } | 1972 | } |
1884 | 1973 | ||
1885 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1); | 1974 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1, 0); |
1886 | if (ret < 0) { | 1975 | if (ret < 0) { |
1887 | if (unlikely(ret == -ENOENT)) | 1976 | if (unlikely(ret == -ENOENT)) |
1888 | printk(KERN_CRIT "%s: key = %llu, level == %d\n", | 1977 | printk(KERN_CRIT "%s: key = %llu, level == %d\n", |
@@ -1890,7 +1979,7 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
1890 | goto out; | 1979 | goto out; |
1891 | } | 1980 | } |
1892 | 1981 | ||
1893 | ret = NILFS_BMAP_USE_VBN(bmap) ? | 1982 | ret = NILFS_BMAP_USE_VBN(btree) ? |
1894 | nilfs_btree_propagate_v(btree, path, level, bh) : | 1983 | nilfs_btree_propagate_v(btree, path, level, bh) : |
1895 | nilfs_btree_propagate_p(btree, path, level, bh); | 1984 | nilfs_btree_propagate_p(btree, path, level, bh); |
1896 | 1985 | ||
@@ -1900,13 +1989,13 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap, | |||
1900 | return ret; | 1989 | return ret; |
1901 | } | 1990 | } |
1902 | 1991 | ||
1903 | static int nilfs_btree_propagate_gc(const struct nilfs_bmap *bmap, | 1992 | static int nilfs_btree_propagate_gc(struct nilfs_bmap *btree, |
1904 | struct buffer_head *bh) | 1993 | struct buffer_head *bh) |
1905 | { | 1994 | { |
1906 | return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), bh->b_blocknr); | 1995 | return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(btree), bh->b_blocknr); |
1907 | } | 1996 | } |
1908 | 1997 | ||
1909 | static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree, | 1998 | static void nilfs_btree_add_dirty_buffer(struct nilfs_bmap *btree, |
1910 | struct list_head *lists, | 1999 | struct list_head *lists, |
1911 | struct buffer_head *bh) | 2000 | struct buffer_head *bh) |
1912 | { | 2001 | { |
@@ -1920,6 +2009,18 @@ static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree, | |||
1920 | node = (struct nilfs_btree_node *)bh->b_data; | 2009 | node = (struct nilfs_btree_node *)bh->b_data; |
1921 | key = nilfs_btree_node_get_key(node, 0); | 2010 | key = nilfs_btree_node_get_key(node, 0); |
1922 | level = nilfs_btree_node_get_level(node); | 2011 | level = nilfs_btree_node_get_level(node); |
2012 | if (level < NILFS_BTREE_LEVEL_NODE_MIN || | ||
2013 | level >= NILFS_BTREE_LEVEL_MAX) { | ||
2014 | dump_stack(); | ||
2015 | printk(KERN_WARNING | ||
2016 | "%s: invalid btree level: %d (key=%llu, ino=%lu, " | ||
2017 | "blocknr=%llu)\n", | ||
2018 | __func__, level, (unsigned long long)key, | ||
2019 | NILFS_BMAP_I(btree)->vfs_inode.i_ino, | ||
2020 | (unsigned long long)bh->b_blocknr); | ||
2021 | return; | ||
2022 | } | ||
2023 | |||
1923 | list_for_each(head, &lists[level]) { | 2024 | list_for_each(head, &lists[level]) { |
1924 | cbh = list_entry(head, struct buffer_head, b_assoc_buffers); | 2025 | cbh = list_entry(head, struct buffer_head, b_assoc_buffers); |
1925 | cnode = (struct nilfs_btree_node *)cbh->b_data; | 2026 | cnode = (struct nilfs_btree_node *)cbh->b_data; |
@@ -1930,11 +2031,10 @@ static void nilfs_btree_add_dirty_buffer(struct nilfs_btree *btree, | |||
1930 | list_add_tail(&bh->b_assoc_buffers, head); | 2031 | list_add_tail(&bh->b_assoc_buffers, head); |
1931 | } | 2032 | } |
1932 | 2033 | ||
1933 | static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap, | 2034 | static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *btree, |
1934 | struct list_head *listp) | 2035 | struct list_head *listp) |
1935 | { | 2036 | { |
1936 | struct nilfs_btree *btree = (struct nilfs_btree *)bmap; | 2037 | struct address_space *btcache = &NILFS_BMAP_I(btree)->i_btnode_cache; |
1937 | struct address_space *btcache = &NILFS_BMAP_I(bmap)->i_btnode_cache; | ||
1938 | struct list_head lists[NILFS_BTREE_LEVEL_MAX]; | 2038 | struct list_head lists[NILFS_BTREE_LEVEL_MAX]; |
1939 | struct pagevec pvec; | 2039 | struct pagevec pvec; |
1940 | struct buffer_head *bh, *head; | 2040 | struct buffer_head *bh, *head; |
@@ -1968,7 +2068,7 @@ static void nilfs_btree_lookup_dirty_buffers(struct nilfs_bmap *bmap, | |||
1968 | list_splice_tail(&lists[level], listp); | 2068 | list_splice_tail(&lists[level], listp); |
1969 | } | 2069 | } |
1970 | 2070 | ||
1971 | static int nilfs_btree_assign_p(struct nilfs_btree *btree, | 2071 | static int nilfs_btree_assign_p(struct nilfs_bmap *btree, |
1972 | struct nilfs_btree_path *path, | 2072 | struct nilfs_btree_path *path, |
1973 | int level, | 2073 | int level, |
1974 | struct buffer_head **bh, | 2074 | struct buffer_head **bh, |
@@ -1978,38 +2078,38 @@ static int nilfs_btree_assign_p(struct nilfs_btree *btree, | |||
1978 | struct nilfs_btree_node *parent; | 2078 | struct nilfs_btree_node *parent; |
1979 | __u64 key; | 2079 | __u64 key; |
1980 | __u64 ptr; | 2080 | __u64 ptr; |
1981 | int ret; | 2081 | int ncmax, ret; |
1982 | 2082 | ||
1983 | parent = nilfs_btree_get_node(btree, path, level + 1); | 2083 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
1984 | ptr = nilfs_btree_node_get_ptr(btree, parent, | 2084 | ptr = nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index, |
1985 | path[level + 1].bp_index); | 2085 | ncmax); |
1986 | if (buffer_nilfs_node(*bh)) { | 2086 | if (buffer_nilfs_node(*bh)) { |
1987 | path[level].bp_ctxt.oldkey = ptr; | 2087 | path[level].bp_ctxt.oldkey = ptr; |
1988 | path[level].bp_ctxt.newkey = blocknr; | 2088 | path[level].bp_ctxt.newkey = blocknr; |
1989 | path[level].bp_ctxt.bh = *bh; | 2089 | path[level].bp_ctxt.bh = *bh; |
1990 | ret = nilfs_btnode_prepare_change_key( | 2090 | ret = nilfs_btnode_prepare_change_key( |
1991 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 2091 | &NILFS_BMAP_I(btree)->i_btnode_cache, |
1992 | &path[level].bp_ctxt); | 2092 | &path[level].bp_ctxt); |
1993 | if (ret < 0) | 2093 | if (ret < 0) |
1994 | return ret; | 2094 | return ret; |
1995 | nilfs_btnode_commit_change_key( | 2095 | nilfs_btnode_commit_change_key( |
1996 | &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, | 2096 | &NILFS_BMAP_I(btree)->i_btnode_cache, |
1997 | &path[level].bp_ctxt); | 2097 | &path[level].bp_ctxt); |
1998 | *bh = path[level].bp_ctxt.bh; | 2098 | *bh = path[level].bp_ctxt.bh; |
1999 | } | 2099 | } |
2000 | 2100 | ||
2001 | nilfs_btree_node_set_ptr(btree, parent, | 2101 | nilfs_btree_node_set_ptr(parent, path[level + 1].bp_index, blocknr, |
2002 | path[level + 1].bp_index, blocknr); | 2102 | ncmax); |
2003 | 2103 | ||
2004 | key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index); | 2104 | key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index); |
2005 | /* on-disk format */ | 2105 | /* on-disk format */ |
2006 | binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 2106 | binfo->bi_dat.bi_blkoff = cpu_to_le64(key); |
2007 | binfo->bi_dat.bi_level = level; | 2107 | binfo->bi_dat.bi_level = level; |
2008 | 2108 | ||
2009 | return 0; | 2109 | return 0; |
2010 | } | 2110 | } |
2011 | 2111 | ||
2012 | static int nilfs_btree_assign_v(struct nilfs_btree *btree, | 2112 | static int nilfs_btree_assign_v(struct nilfs_bmap *btree, |
2013 | struct nilfs_btree_path *path, | 2113 | struct nilfs_btree_path *path, |
2014 | int level, | 2114 | int level, |
2015 | struct buffer_head **bh, | 2115 | struct buffer_head **bh, |
@@ -2017,15 +2117,15 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree, | |||
2017 | union nilfs_binfo *binfo) | 2117 | union nilfs_binfo *binfo) |
2018 | { | 2118 | { |
2019 | struct nilfs_btree_node *parent; | 2119 | struct nilfs_btree_node *parent; |
2020 | struct inode *dat = nilfs_bmap_get_dat(&btree->bt_bmap); | 2120 | struct inode *dat = nilfs_bmap_get_dat(btree); |
2021 | __u64 key; | 2121 | __u64 key; |
2022 | __u64 ptr; | 2122 | __u64 ptr; |
2023 | union nilfs_bmap_ptr_req req; | 2123 | union nilfs_bmap_ptr_req req; |
2024 | int ret; | 2124 | int ncmax, ret; |
2025 | 2125 | ||
2026 | parent = nilfs_btree_get_node(btree, path, level + 1); | 2126 | parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); |
2027 | ptr = nilfs_btree_node_get_ptr(btree, parent, | 2127 | ptr = nilfs_btree_node_get_ptr(parent, path[level + 1].bp_index, |
2028 | path[level + 1].bp_index); | 2128 | ncmax); |
2029 | req.bpr_ptr = ptr; | 2129 | req.bpr_ptr = ptr; |
2030 | ret = nilfs_dat_prepare_start(dat, &req.bpr_req); | 2130 | ret = nilfs_dat_prepare_start(dat, &req.bpr_req); |
2031 | if (ret < 0) | 2131 | if (ret < 0) |
@@ -2034,24 +2134,22 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree, | |||
2034 | 2134 | ||
2035 | key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index); | 2135 | key = nilfs_btree_node_get_key(parent, path[level + 1].bp_index); |
2036 | /* on-disk format */ | 2136 | /* on-disk format */ |
2037 | binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr); | 2137 | binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr); |
2038 | binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 2138 | binfo->bi_v.bi_blkoff = cpu_to_le64(key); |
2039 | 2139 | ||
2040 | return 0; | 2140 | return 0; |
2041 | } | 2141 | } |
2042 | 2142 | ||
2043 | static int nilfs_btree_assign(struct nilfs_bmap *bmap, | 2143 | static int nilfs_btree_assign(struct nilfs_bmap *btree, |
2044 | struct buffer_head **bh, | 2144 | struct buffer_head **bh, |
2045 | sector_t blocknr, | 2145 | sector_t blocknr, |
2046 | union nilfs_binfo *binfo) | 2146 | union nilfs_binfo *binfo) |
2047 | { | 2147 | { |
2048 | struct nilfs_btree *btree; | ||
2049 | struct nilfs_btree_path *path; | 2148 | struct nilfs_btree_path *path; |
2050 | struct nilfs_btree_node *node; | 2149 | struct nilfs_btree_node *node; |
2051 | __u64 key; | 2150 | __u64 key; |
2052 | int level, ret; | 2151 | int level, ret; |
2053 | 2152 | ||
2054 | btree = (struct nilfs_btree *)bmap; | ||
2055 | path = nilfs_btree_alloc_path(); | 2153 | path = nilfs_btree_alloc_path(); |
2056 | if (path == NULL) | 2154 | if (path == NULL) |
2057 | return -ENOMEM; | 2155 | return -ENOMEM; |
@@ -2061,17 +2159,17 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, | |||
2061 | key = nilfs_btree_node_get_key(node, 0); | 2159 | key = nilfs_btree_node_get_key(node, 0); |
2062 | level = nilfs_btree_node_get_level(node); | 2160 | level = nilfs_btree_node_get_level(node); |
2063 | } else { | 2161 | } else { |
2064 | key = nilfs_bmap_data_get_key(bmap, *bh); | 2162 | key = nilfs_bmap_data_get_key(btree, *bh); |
2065 | level = NILFS_BTREE_LEVEL_DATA; | 2163 | level = NILFS_BTREE_LEVEL_DATA; |
2066 | } | 2164 | } |
2067 | 2165 | ||
2068 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1); | 2166 | ret = nilfs_btree_do_lookup(btree, path, key, NULL, level + 1, 0); |
2069 | if (ret < 0) { | 2167 | if (ret < 0) { |
2070 | WARN_ON(ret == -ENOENT); | 2168 | WARN_ON(ret == -ENOENT); |
2071 | goto out; | 2169 | goto out; |
2072 | } | 2170 | } |
2073 | 2171 | ||
2074 | ret = NILFS_BMAP_USE_VBN(bmap) ? | 2172 | ret = NILFS_BMAP_USE_VBN(btree) ? |
2075 | nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) : | 2173 | nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) : |
2076 | nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo); | 2174 | nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo); |
2077 | 2175 | ||
@@ -2081,7 +2179,7 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap, | |||
2081 | return ret; | 2179 | return ret; |
2082 | } | 2180 | } |
2083 | 2181 | ||
2084 | static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap, | 2182 | static int nilfs_btree_assign_gc(struct nilfs_bmap *btree, |
2085 | struct buffer_head **bh, | 2183 | struct buffer_head **bh, |
2086 | sector_t blocknr, | 2184 | sector_t blocknr, |
2087 | union nilfs_binfo *binfo) | 2185 | union nilfs_binfo *binfo) |
@@ -2090,7 +2188,7 @@ static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap, | |||
2090 | __u64 key; | 2188 | __u64 key; |
2091 | int ret; | 2189 | int ret; |
2092 | 2190 | ||
2093 | ret = nilfs_dat_move(nilfs_bmap_get_dat(bmap), (*bh)->b_blocknr, | 2191 | ret = nilfs_dat_move(nilfs_bmap_get_dat(btree), (*bh)->b_blocknr, |
2094 | blocknr); | 2192 | blocknr); |
2095 | if (ret < 0) | 2193 | if (ret < 0) |
2096 | return ret; | 2194 | return ret; |
@@ -2099,29 +2197,27 @@ static int nilfs_btree_assign_gc(struct nilfs_bmap *bmap, | |||
2099 | node = (struct nilfs_btree_node *)(*bh)->b_data; | 2197 | node = (struct nilfs_btree_node *)(*bh)->b_data; |
2100 | key = nilfs_btree_node_get_key(node, 0); | 2198 | key = nilfs_btree_node_get_key(node, 0); |
2101 | } else | 2199 | } else |
2102 | key = nilfs_bmap_data_get_key(bmap, *bh); | 2200 | key = nilfs_bmap_data_get_key(btree, *bh); |
2103 | 2201 | ||
2104 | /* on-disk format */ | 2202 | /* on-disk format */ |
2105 | binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr); | 2203 | binfo->bi_v.bi_vblocknr = cpu_to_le64((*bh)->b_blocknr); |
2106 | binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 2204 | binfo->bi_v.bi_blkoff = cpu_to_le64(key); |
2107 | 2205 | ||
2108 | return 0; | 2206 | return 0; |
2109 | } | 2207 | } |
2110 | 2208 | ||
2111 | static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) | 2209 | static int nilfs_btree_mark(struct nilfs_bmap *btree, __u64 key, int level) |
2112 | { | 2210 | { |
2113 | struct buffer_head *bh; | 2211 | struct buffer_head *bh; |
2114 | struct nilfs_btree *btree; | ||
2115 | struct nilfs_btree_path *path; | 2212 | struct nilfs_btree_path *path; |
2116 | __u64 ptr; | 2213 | __u64 ptr; |
2117 | int ret; | 2214 | int ret; |
2118 | 2215 | ||
2119 | btree = (struct nilfs_btree *)bmap; | ||
2120 | path = nilfs_btree_alloc_path(); | 2216 | path = nilfs_btree_alloc_path(); |
2121 | if (path == NULL) | 2217 | if (path == NULL) |
2122 | return -ENOMEM; | 2218 | return -ENOMEM; |
2123 | 2219 | ||
2124 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1); | 2220 | ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level + 1, 0); |
2125 | if (ret < 0) { | 2221 | if (ret < 0) { |
2126 | WARN_ON(ret == -ENOENT); | 2222 | WARN_ON(ret == -ENOENT); |
2127 | goto out; | 2223 | goto out; |
@@ -2135,8 +2231,8 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level) | |||
2135 | if (!buffer_dirty(bh)) | 2231 | if (!buffer_dirty(bh)) |
2136 | nilfs_btnode_mark_dirty(bh); | 2232 | nilfs_btnode_mark_dirty(bh); |
2137 | brelse(bh); | 2233 | brelse(bh); |
2138 | if (!nilfs_bmap_dirty(&btree->bt_bmap)) | 2234 | if (!nilfs_bmap_dirty(btree)) |
2139 | nilfs_bmap_set_dirty(&btree->bt_bmap); | 2235 | nilfs_bmap_set_dirty(btree); |
2140 | 2236 | ||
2141 | out: | 2237 | out: |
2142 | nilfs_btree_free_path(path); | 2238 | nilfs_btree_free_path(path); |
@@ -2186,10 +2282,14 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { | |||
2186 | int nilfs_btree_init(struct nilfs_bmap *bmap) | 2282 | int nilfs_btree_init(struct nilfs_bmap *bmap) |
2187 | { | 2283 | { |
2188 | bmap->b_ops = &nilfs_btree_ops; | 2284 | bmap->b_ops = &nilfs_btree_ops; |
2285 | bmap->b_nchildren_per_block = | ||
2286 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap)); | ||
2189 | return 0; | 2287 | return 0; |
2190 | } | 2288 | } |
2191 | 2289 | ||
2192 | void nilfs_btree_init_gc(struct nilfs_bmap *bmap) | 2290 | void nilfs_btree_init_gc(struct nilfs_bmap *bmap) |
2193 | { | 2291 | { |
2194 | bmap->b_ops = &nilfs_btree_ops_gc; | 2292 | bmap->b_ops = &nilfs_btree_ops_gc; |
2293 | bmap->b_nchildren_per_block = | ||
2294 | NILFS_BTREE_NODE_NCHILDREN_MAX(nilfs_btree_node_size(bmap)); | ||
2195 | } | 2295 | } |
diff --git a/fs/nilfs2/btree.h b/fs/nilfs2/btree.h index 43c8c5b541fd..22c02e35b6ef 100644 --- a/fs/nilfs2/btree.h +++ b/fs/nilfs2/btree.h | |||
@@ -31,14 +31,6 @@ | |||
31 | #include "bmap.h" | 31 | #include "bmap.h" |
32 | 32 | ||
33 | /** | 33 | /** |
34 | * struct nilfs_btree - B-tree structure | ||
35 | * @bt_bmap: bmap base structure | ||
36 | */ | ||
37 | struct nilfs_btree { | ||
38 | struct nilfs_bmap bt_bmap; | ||
39 | }; | ||
40 | |||
41 | /** | ||
42 | * struct nilfs_btree_path - A path on which B-tree operations are executed | 34 | * struct nilfs_btree_path - A path on which B-tree operations are executed |
43 | * @bp_bh: buffer head of node block | 35 | * @bp_bh: buffer head of node block |
44 | * @bp_sib_bh: buffer head of sibling node block | 36 | * @bp_sib_bh: buffer head of sibling node block |
@@ -54,7 +46,7 @@ struct nilfs_btree_path { | |||
54 | union nilfs_bmap_ptr_req bp_oldreq; | 46 | union nilfs_bmap_ptr_req bp_oldreq; |
55 | union nilfs_bmap_ptr_req bp_newreq; | 47 | union nilfs_bmap_ptr_req bp_newreq; |
56 | struct nilfs_btnode_chkey_ctxt bp_ctxt; | 48 | struct nilfs_btnode_chkey_ctxt bp_ctxt; |
57 | void (*bp_op)(struct nilfs_btree *, struct nilfs_btree_path *, | 49 | void (*bp_op)(struct nilfs_bmap *, struct nilfs_btree_path *, |
58 | int, __u64 *, __u64 *); | 50 | int, __u64 *, __u64 *); |
59 | }; | 51 | }; |
60 | 52 | ||
@@ -80,4 +72,6 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *, __u64, __u64, | |||
80 | const __u64 *, const __u64 *, int); | 72 | const __u64 *, const __u64 *, int); |
81 | void nilfs_btree_init_gc(struct nilfs_bmap *); | 73 | void nilfs_btree_init_gc(struct nilfs_bmap *); |
82 | 74 | ||
75 | int nilfs_btree_broken_node_block(struct buffer_head *bh); | ||
76 | |||
83 | #endif /* _NILFS_BTREE_H */ | 77 | #endif /* _NILFS_BTREE_H */ |
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index 85c89dfc71f0..b60277b44468 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c | |||
@@ -141,7 +141,7 @@ static void nilfs_check_page(struct page *page) | |||
141 | } | 141 | } |
142 | for (offs = 0; offs <= limit - NILFS_DIR_REC_LEN(1); offs += rec_len) { | 142 | for (offs = 0; offs <= limit - NILFS_DIR_REC_LEN(1); offs += rec_len) { |
143 | p = (struct nilfs_dir_entry *)(kaddr + offs); | 143 | p = (struct nilfs_dir_entry *)(kaddr + offs); |
144 | rec_len = le16_to_cpu(p->rec_len); | 144 | rec_len = nilfs_rec_len_from_disk(p->rec_len); |
145 | 145 | ||
146 | if (rec_len < NILFS_DIR_REC_LEN(1)) | 146 | if (rec_len < NILFS_DIR_REC_LEN(1)) |
147 | goto Eshort; | 147 | goto Eshort; |
@@ -199,13 +199,10 @@ fail: | |||
199 | static struct page *nilfs_get_page(struct inode *dir, unsigned long n) | 199 | static struct page *nilfs_get_page(struct inode *dir, unsigned long n) |
200 | { | 200 | { |
201 | struct address_space *mapping = dir->i_mapping; | 201 | struct address_space *mapping = dir->i_mapping; |
202 | struct page *page = read_cache_page(mapping, n, | 202 | struct page *page = read_mapping_page(mapping, n, NULL); |
203 | (filler_t *)mapping->a_ops->readpage, NULL); | 203 | |
204 | if (!IS_ERR(page)) { | 204 | if (!IS_ERR(page)) { |
205 | wait_on_page_locked(page); | ||
206 | kmap(page); | 205 | kmap(page); |
207 | if (!PageUptodate(page)) | ||
208 | goto fail; | ||
209 | if (!PageChecked(page)) | 206 | if (!PageChecked(page)) |
210 | nilfs_check_page(page); | 207 | nilfs_check_page(page); |
211 | if (PageError(page)) | 208 | if (PageError(page)) |
@@ -238,7 +235,8 @@ nilfs_match(int len, const unsigned char *name, struct nilfs_dir_entry *de) | |||
238 | */ | 235 | */ |
239 | static struct nilfs_dir_entry *nilfs_next_entry(struct nilfs_dir_entry *p) | 236 | static struct nilfs_dir_entry *nilfs_next_entry(struct nilfs_dir_entry *p) |
240 | { | 237 | { |
241 | return (struct nilfs_dir_entry *)((char *)p + le16_to_cpu(p->rec_len)); | 238 | return (struct nilfs_dir_entry *)((char *)p + |
239 | nilfs_rec_len_from_disk(p->rec_len)); | ||
242 | } | 240 | } |
243 | 241 | ||
244 | static unsigned char | 242 | static unsigned char |
@@ -329,7 +327,7 @@ static int nilfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
329 | goto success; | 327 | goto success; |
330 | } | 328 | } |
331 | } | 329 | } |
332 | filp->f_pos += le16_to_cpu(de->rec_len); | 330 | filp->f_pos += nilfs_rec_len_from_disk(de->rec_len); |
333 | } | 331 | } |
334 | nilfs_put_page(page); | 332 | nilfs_put_page(page); |
335 | } | 333 | } |
@@ -444,7 +442,7 @@ void nilfs_set_link(struct inode *dir, struct nilfs_dir_entry *de, | |||
444 | struct page *page, struct inode *inode) | 442 | struct page *page, struct inode *inode) |
445 | { | 443 | { |
446 | unsigned from = (char *) de - (char *) page_address(page); | 444 | unsigned from = (char *) de - (char *) page_address(page); |
447 | unsigned to = from + le16_to_cpu(de->rec_len); | 445 | unsigned to = from + nilfs_rec_len_from_disk(de->rec_len); |
448 | struct address_space *mapping = page->mapping; | 446 | struct address_space *mapping = page->mapping; |
449 | int err; | 447 | int err; |
450 | 448 | ||
@@ -500,7 +498,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode) | |||
500 | /* We hit i_size */ | 498 | /* We hit i_size */ |
501 | name_len = 0; | 499 | name_len = 0; |
502 | rec_len = chunk_size; | 500 | rec_len = chunk_size; |
503 | de->rec_len = cpu_to_le16(chunk_size); | 501 | de->rec_len = nilfs_rec_len_to_disk(chunk_size); |
504 | de->inode = 0; | 502 | de->inode = 0; |
505 | goto got_it; | 503 | goto got_it; |
506 | } | 504 | } |
@@ -514,7 +512,7 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode) | |||
514 | if (nilfs_match(namelen, name, de)) | 512 | if (nilfs_match(namelen, name, de)) |
515 | goto out_unlock; | 513 | goto out_unlock; |
516 | name_len = NILFS_DIR_REC_LEN(de->name_len); | 514 | name_len = NILFS_DIR_REC_LEN(de->name_len); |
517 | rec_len = le16_to_cpu(de->rec_len); | 515 | rec_len = nilfs_rec_len_from_disk(de->rec_len); |
518 | if (!de->inode && rec_len >= reclen) | 516 | if (!de->inode && rec_len >= reclen) |
519 | goto got_it; | 517 | goto got_it; |
520 | if (rec_len >= name_len + reclen) | 518 | if (rec_len >= name_len + reclen) |
@@ -537,8 +535,8 @@ got_it: | |||
537 | struct nilfs_dir_entry *de1; | 535 | struct nilfs_dir_entry *de1; |
538 | 536 | ||
539 | de1 = (struct nilfs_dir_entry *)((char *)de + name_len); | 537 | de1 = (struct nilfs_dir_entry *)((char *)de + name_len); |
540 | de1->rec_len = cpu_to_le16(rec_len - name_len); | 538 | de1->rec_len = nilfs_rec_len_to_disk(rec_len - name_len); |
541 | de->rec_len = cpu_to_le16(name_len); | 539 | de->rec_len = nilfs_rec_len_to_disk(name_len); |
542 | de = de1; | 540 | de = de1; |
543 | } | 541 | } |
544 | de->name_len = namelen; | 542 | de->name_len = namelen; |
@@ -569,7 +567,8 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) | |||
569 | struct inode *inode = mapping->host; | 567 | struct inode *inode = mapping->host; |
570 | char *kaddr = page_address(page); | 568 | char *kaddr = page_address(page); |
571 | unsigned from = ((char *)dir - kaddr) & ~(nilfs_chunk_size(inode) - 1); | 569 | unsigned from = ((char *)dir - kaddr) & ~(nilfs_chunk_size(inode) - 1); |
572 | unsigned to = ((char *)dir - kaddr) + le16_to_cpu(dir->rec_len); | 570 | unsigned to = ((char *)dir - kaddr) + |
571 | nilfs_rec_len_from_disk(dir->rec_len); | ||
573 | struct nilfs_dir_entry *pde = NULL; | 572 | struct nilfs_dir_entry *pde = NULL; |
574 | struct nilfs_dir_entry *de = (struct nilfs_dir_entry *)(kaddr + from); | 573 | struct nilfs_dir_entry *de = (struct nilfs_dir_entry *)(kaddr + from); |
575 | int err; | 574 | int err; |
@@ -590,7 +589,7 @@ int nilfs_delete_entry(struct nilfs_dir_entry *dir, struct page *page) | |||
590 | err = nilfs_prepare_chunk(page, mapping, from, to); | 589 | err = nilfs_prepare_chunk(page, mapping, from, to); |
591 | BUG_ON(err); | 590 | BUG_ON(err); |
592 | if (pde) | 591 | if (pde) |
593 | pde->rec_len = cpu_to_le16(to - from); | 592 | pde->rec_len = nilfs_rec_len_to_disk(to - from); |
594 | dir->inode = 0; | 593 | dir->inode = 0; |
595 | nilfs_commit_chunk(page, mapping, from, to); | 594 | nilfs_commit_chunk(page, mapping, from, to); |
596 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | 595 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; |
@@ -624,14 +623,14 @@ int nilfs_make_empty(struct inode *inode, struct inode *parent) | |||
624 | memset(kaddr, 0, chunk_size); | 623 | memset(kaddr, 0, chunk_size); |
625 | de = (struct nilfs_dir_entry *)kaddr; | 624 | de = (struct nilfs_dir_entry *)kaddr; |
626 | de->name_len = 1; | 625 | de->name_len = 1; |
627 | de->rec_len = cpu_to_le16(NILFS_DIR_REC_LEN(1)); | 626 | de->rec_len = nilfs_rec_len_to_disk(NILFS_DIR_REC_LEN(1)); |
628 | memcpy(de->name, ".\0\0", 4); | 627 | memcpy(de->name, ".\0\0", 4); |
629 | de->inode = cpu_to_le64(inode->i_ino); | 628 | de->inode = cpu_to_le64(inode->i_ino); |
630 | nilfs_set_de_type(de, inode); | 629 | nilfs_set_de_type(de, inode); |
631 | 630 | ||
632 | de = (struct nilfs_dir_entry *)(kaddr + NILFS_DIR_REC_LEN(1)); | 631 | de = (struct nilfs_dir_entry *)(kaddr + NILFS_DIR_REC_LEN(1)); |
633 | de->name_len = 2; | 632 | de->name_len = 2; |
634 | de->rec_len = cpu_to_le16(chunk_size - NILFS_DIR_REC_LEN(1)); | 633 | de->rec_len = nilfs_rec_len_to_disk(chunk_size - NILFS_DIR_REC_LEN(1)); |
635 | de->inode = cpu_to_le64(parent->i_ino); | 634 | de->inode = cpu_to_le64(parent->i_ino); |
636 | memcpy(de->name, "..\0", 4); | 635 | memcpy(de->name, "..\0", 4); |
637 | nilfs_set_de_type(de, inode); | 636 | nilfs_set_de_type(de, inode); |
diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c index 236753df5cdf..324d80c57518 100644 --- a/fs/nilfs2/direct.c +++ b/fs/nilfs2/direct.c | |||
@@ -27,47 +27,43 @@ | |||
27 | #include "alloc.h" | 27 | #include "alloc.h" |
28 | #include "dat.h" | 28 | #include "dat.h" |
29 | 29 | ||
30 | static inline __le64 *nilfs_direct_dptrs(const struct nilfs_direct *direct) | 30 | static inline __le64 *nilfs_direct_dptrs(const struct nilfs_bmap *direct) |
31 | { | 31 | { |
32 | return (__le64 *) | 32 | return (__le64 *) |
33 | ((struct nilfs_direct_node *)direct->d_bmap.b_u.u_data + 1); | 33 | ((struct nilfs_direct_node *)direct->b_u.u_data + 1); |
34 | } | 34 | } |
35 | 35 | ||
36 | static inline __u64 | 36 | static inline __u64 |
37 | nilfs_direct_get_ptr(const struct nilfs_direct *direct, __u64 key) | 37 | nilfs_direct_get_ptr(const struct nilfs_bmap *direct, __u64 key) |
38 | { | 38 | { |
39 | return nilfs_bmap_dptr_to_ptr(*(nilfs_direct_dptrs(direct) + key)); | 39 | return le64_to_cpu(*(nilfs_direct_dptrs(direct) + key)); |
40 | } | 40 | } |
41 | 41 | ||
42 | static inline void nilfs_direct_set_ptr(struct nilfs_direct *direct, | 42 | static inline void nilfs_direct_set_ptr(struct nilfs_bmap *direct, |
43 | __u64 key, __u64 ptr) | 43 | __u64 key, __u64 ptr) |
44 | { | 44 | { |
45 | *(nilfs_direct_dptrs(direct) + key) = nilfs_bmap_ptr_to_dptr(ptr); | 45 | *(nilfs_direct_dptrs(direct) + key) = cpu_to_le64(ptr); |
46 | } | 46 | } |
47 | 47 | ||
48 | static int nilfs_direct_lookup(const struct nilfs_bmap *bmap, | 48 | static int nilfs_direct_lookup(const struct nilfs_bmap *direct, |
49 | __u64 key, int level, __u64 *ptrp) | 49 | __u64 key, int level, __u64 *ptrp) |
50 | { | 50 | { |
51 | struct nilfs_direct *direct; | ||
52 | __u64 ptr; | 51 | __u64 ptr; |
53 | 52 | ||
54 | direct = (struct nilfs_direct *)bmap; /* XXX: use macro for level 1 */ | ||
55 | if (key > NILFS_DIRECT_KEY_MAX || level != 1) | 53 | if (key > NILFS_DIRECT_KEY_MAX || level != 1) |
56 | return -ENOENT; | 54 | return -ENOENT; |
57 | ptr = nilfs_direct_get_ptr(direct, key); | 55 | ptr = nilfs_direct_get_ptr(direct, key); |
58 | if (ptr == NILFS_BMAP_INVALID_PTR) | 56 | if (ptr == NILFS_BMAP_INVALID_PTR) |
59 | return -ENOENT; | 57 | return -ENOENT; |
60 | 58 | ||
61 | if (ptrp != NULL) | 59 | *ptrp = ptr; |
62 | *ptrp = ptr; | ||
63 | return 0; | 60 | return 0; |
64 | } | 61 | } |
65 | 62 | ||
66 | static int nilfs_direct_lookup_contig(const struct nilfs_bmap *bmap, | 63 | static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct, |
67 | __u64 key, __u64 *ptrp, | 64 | __u64 key, __u64 *ptrp, |
68 | unsigned maxblocks) | 65 | unsigned maxblocks) |
69 | { | 66 | { |
70 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; | ||
71 | struct inode *dat = NULL; | 67 | struct inode *dat = NULL; |
72 | __u64 ptr, ptr2; | 68 | __u64 ptr, ptr2; |
73 | sector_t blocknr; | 69 | sector_t blocknr; |
@@ -79,8 +75,8 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *bmap, | |||
79 | if (ptr == NILFS_BMAP_INVALID_PTR) | 75 | if (ptr == NILFS_BMAP_INVALID_PTR) |
80 | return -ENOENT; | 76 | return -ENOENT; |
81 | 77 | ||
82 | if (NILFS_BMAP_USE_VBN(bmap)) { | 78 | if (NILFS_BMAP_USE_VBN(direct)) { |
83 | dat = nilfs_bmap_get_dat(bmap); | 79 | dat = nilfs_bmap_get_dat(direct); |
84 | ret = nilfs_dat_translate(dat, ptr, &blocknr); | 80 | ret = nilfs_dat_translate(dat, ptr, &blocknr); |
85 | if (ret < 0) | 81 | if (ret < 0) |
86 | return ret; | 82 | return ret; |
@@ -106,29 +102,21 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *bmap, | |||
106 | } | 102 | } |
107 | 103 | ||
108 | static __u64 | 104 | static __u64 |
109 | nilfs_direct_find_target_v(const struct nilfs_direct *direct, __u64 key) | 105 | nilfs_direct_find_target_v(const struct nilfs_bmap *direct, __u64 key) |
110 | { | 106 | { |
111 | __u64 ptr; | 107 | __u64 ptr; |
112 | 108 | ||
113 | ptr = nilfs_bmap_find_target_seq(&direct->d_bmap, key); | 109 | ptr = nilfs_bmap_find_target_seq(direct, key); |
114 | if (ptr != NILFS_BMAP_INVALID_PTR) | 110 | if (ptr != NILFS_BMAP_INVALID_PTR) |
115 | /* sequential access */ | 111 | /* sequential access */ |
116 | return ptr; | 112 | return ptr; |
117 | else | 113 | else |
118 | /* block group */ | 114 | /* block group */ |
119 | return nilfs_bmap_find_target_in_group(&direct->d_bmap); | 115 | return nilfs_bmap_find_target_in_group(direct); |
120 | } | ||
121 | |||
122 | static void nilfs_direct_set_target_v(struct nilfs_direct *direct, | ||
123 | __u64 key, __u64 ptr) | ||
124 | { | ||
125 | direct->d_bmap.b_last_allocated_key = key; | ||
126 | direct->d_bmap.b_last_allocated_ptr = ptr; | ||
127 | } | 116 | } |
128 | 117 | ||
129 | static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | 118 | static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) |
130 | { | 119 | { |
131 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; | ||
132 | union nilfs_bmap_ptr_req req; | 120 | union nilfs_bmap_ptr_req req; |
133 | struct inode *dat = NULL; | 121 | struct inode *dat = NULL; |
134 | struct buffer_head *bh; | 122 | struct buffer_head *bh; |
@@ -136,11 +124,11 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
136 | 124 | ||
137 | if (key > NILFS_DIRECT_KEY_MAX) | 125 | if (key > NILFS_DIRECT_KEY_MAX) |
138 | return -ENOENT; | 126 | return -ENOENT; |
139 | if (nilfs_direct_get_ptr(direct, key) != NILFS_BMAP_INVALID_PTR) | 127 | if (nilfs_direct_get_ptr(bmap, key) != NILFS_BMAP_INVALID_PTR) |
140 | return -EEXIST; | 128 | return -EEXIST; |
141 | 129 | ||
142 | if (NILFS_BMAP_USE_VBN(bmap)) { | 130 | if (NILFS_BMAP_USE_VBN(bmap)) { |
143 | req.bpr_ptr = nilfs_direct_find_target_v(direct, key); | 131 | req.bpr_ptr = nilfs_direct_find_target_v(bmap, key); |
144 | dat = nilfs_bmap_get_dat(bmap); | 132 | dat = nilfs_bmap_get_dat(bmap); |
145 | } | 133 | } |
146 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, &req, dat); | 134 | ret = nilfs_bmap_prepare_alloc_ptr(bmap, &req, dat); |
@@ -150,13 +138,13 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
150 | set_buffer_nilfs_volatile(bh); | 138 | set_buffer_nilfs_volatile(bh); |
151 | 139 | ||
152 | nilfs_bmap_commit_alloc_ptr(bmap, &req, dat); | 140 | nilfs_bmap_commit_alloc_ptr(bmap, &req, dat); |
153 | nilfs_direct_set_ptr(direct, key, req.bpr_ptr); | 141 | nilfs_direct_set_ptr(bmap, key, req.bpr_ptr); |
154 | 142 | ||
155 | if (!nilfs_bmap_dirty(bmap)) | 143 | if (!nilfs_bmap_dirty(bmap)) |
156 | nilfs_bmap_set_dirty(bmap); | 144 | nilfs_bmap_set_dirty(bmap); |
157 | 145 | ||
158 | if (NILFS_BMAP_USE_VBN(bmap)) | 146 | if (NILFS_BMAP_USE_VBN(bmap)) |
159 | nilfs_direct_set_target_v(direct, key, req.bpr_ptr); | 147 | nilfs_bmap_set_target_v(bmap, key, req.bpr_ptr); |
160 | 148 | ||
161 | nilfs_bmap_add_blocks(bmap, 1); | 149 | nilfs_bmap_add_blocks(bmap, 1); |
162 | } | 150 | } |
@@ -165,33 +153,30 @@ static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) | |||
165 | 153 | ||
166 | static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) | 154 | static int nilfs_direct_delete(struct nilfs_bmap *bmap, __u64 key) |
167 | { | 155 | { |
168 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; | ||
169 | union nilfs_bmap_ptr_req req; | 156 | union nilfs_bmap_ptr_req req; |
170 | struct inode *dat; | 157 | struct inode *dat; |
171 | int ret; | 158 | int ret; |
172 | 159 | ||
173 | if (key > NILFS_DIRECT_KEY_MAX || | 160 | if (key > NILFS_DIRECT_KEY_MAX || |
174 | nilfs_direct_get_ptr(direct, key) == NILFS_BMAP_INVALID_PTR) | 161 | nilfs_direct_get_ptr(bmap, key) == NILFS_BMAP_INVALID_PTR) |
175 | return -ENOENT; | 162 | return -ENOENT; |
176 | 163 | ||
177 | dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL; | 164 | dat = NILFS_BMAP_USE_VBN(bmap) ? nilfs_bmap_get_dat(bmap) : NULL; |
178 | req.bpr_ptr = nilfs_direct_get_ptr(direct, key); | 165 | req.bpr_ptr = nilfs_direct_get_ptr(bmap, key); |
179 | 166 | ||
180 | ret = nilfs_bmap_prepare_end_ptr(bmap, &req, dat); | 167 | ret = nilfs_bmap_prepare_end_ptr(bmap, &req, dat); |
181 | if (!ret) { | 168 | if (!ret) { |
182 | nilfs_bmap_commit_end_ptr(bmap, &req, dat); | 169 | nilfs_bmap_commit_end_ptr(bmap, &req, dat); |
183 | nilfs_direct_set_ptr(direct, key, NILFS_BMAP_INVALID_PTR); | 170 | nilfs_direct_set_ptr(bmap, key, NILFS_BMAP_INVALID_PTR); |
184 | nilfs_bmap_sub_blocks(bmap, 1); | 171 | nilfs_bmap_sub_blocks(bmap, 1); |
185 | } | 172 | } |
186 | return ret; | 173 | return ret; |
187 | } | 174 | } |
188 | 175 | ||
189 | static int nilfs_direct_last_key(const struct nilfs_bmap *bmap, __u64 *keyp) | 176 | static int nilfs_direct_last_key(const struct nilfs_bmap *direct, __u64 *keyp) |
190 | { | 177 | { |
191 | struct nilfs_direct *direct; | ||
192 | __u64 key, lastkey; | 178 | __u64 key, lastkey; |
193 | 179 | ||
194 | direct = (struct nilfs_direct *)bmap; | ||
195 | lastkey = NILFS_DIRECT_KEY_MAX + 1; | 180 | lastkey = NILFS_DIRECT_KEY_MAX + 1; |
196 | for (key = NILFS_DIRECT_KEY_MIN; key <= NILFS_DIRECT_KEY_MAX; key++) | 181 | for (key = NILFS_DIRECT_KEY_MIN; key <= NILFS_DIRECT_KEY_MAX; key++) |
197 | if (nilfs_direct_get_ptr(direct, key) != | 182 | if (nilfs_direct_get_ptr(direct, key) != |
@@ -211,15 +196,13 @@ static int nilfs_direct_check_insert(const struct nilfs_bmap *bmap, __u64 key) | |||
211 | return key > NILFS_DIRECT_KEY_MAX; | 196 | return key > NILFS_DIRECT_KEY_MAX; |
212 | } | 197 | } |
213 | 198 | ||
214 | static int nilfs_direct_gather_data(struct nilfs_bmap *bmap, | 199 | static int nilfs_direct_gather_data(struct nilfs_bmap *direct, |
215 | __u64 *keys, __u64 *ptrs, int nitems) | 200 | __u64 *keys, __u64 *ptrs, int nitems) |
216 | { | 201 | { |
217 | struct nilfs_direct *direct; | ||
218 | __u64 key; | 202 | __u64 key; |
219 | __u64 ptr; | 203 | __u64 ptr; |
220 | int n; | 204 | int n; |
221 | 205 | ||
222 | direct = (struct nilfs_direct *)bmap; | ||
223 | if (nitems > NILFS_DIRECT_NBLOCKS) | 206 | if (nitems > NILFS_DIRECT_NBLOCKS) |
224 | nitems = NILFS_DIRECT_NBLOCKS; | 207 | nitems = NILFS_DIRECT_NBLOCKS; |
225 | n = 0; | 208 | n = 0; |
@@ -237,7 +220,6 @@ static int nilfs_direct_gather_data(struct nilfs_bmap *bmap, | |||
237 | int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, | 220 | int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, |
238 | __u64 key, __u64 *keys, __u64 *ptrs, int n) | 221 | __u64 key, __u64 *keys, __u64 *ptrs, int n) |
239 | { | 222 | { |
240 | struct nilfs_direct *direct; | ||
241 | __le64 *dptrs; | 223 | __le64 *dptrs; |
242 | int ret, i, j; | 224 | int ret, i, j; |
243 | 225 | ||
@@ -253,12 +235,11 @@ int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, | |||
253 | bmap->b_ops->bop_clear(bmap); | 235 | bmap->b_ops->bop_clear(bmap); |
254 | 236 | ||
255 | /* convert */ | 237 | /* convert */ |
256 | direct = (struct nilfs_direct *)bmap; | 238 | dptrs = nilfs_direct_dptrs(bmap); |
257 | dptrs = nilfs_direct_dptrs(direct); | ||
258 | for (i = 0, j = 0; i < NILFS_DIRECT_NBLOCKS; i++) { | 239 | for (i = 0, j = 0; i < NILFS_DIRECT_NBLOCKS; i++) { |
259 | if ((j < n) && (i == keys[j])) { | 240 | if ((j < n) && (i == keys[j])) { |
260 | dptrs[i] = (i != key) ? | 241 | dptrs[i] = (i != key) ? |
261 | nilfs_bmap_ptr_to_dptr(ptrs[j]) : | 242 | cpu_to_le64(ptrs[j]) : |
262 | NILFS_BMAP_INVALID_PTR; | 243 | NILFS_BMAP_INVALID_PTR; |
263 | j++; | 244 | j++; |
264 | } else | 245 | } else |
@@ -269,10 +250,9 @@ int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, | |||
269 | return 0; | 250 | return 0; |
270 | } | 251 | } |
271 | 252 | ||
272 | static int nilfs_direct_propagate(const struct nilfs_bmap *bmap, | 253 | static int nilfs_direct_propagate(struct nilfs_bmap *bmap, |
273 | struct buffer_head *bh) | 254 | struct buffer_head *bh) |
274 | { | 255 | { |
275 | struct nilfs_direct *direct = (struct nilfs_direct *)bmap; | ||
276 | struct nilfs_palloc_req oldreq, newreq; | 256 | struct nilfs_palloc_req oldreq, newreq; |
277 | struct inode *dat; | 257 | struct inode *dat; |
278 | __u64 key; | 258 | __u64 key; |
@@ -284,7 +264,7 @@ static int nilfs_direct_propagate(const struct nilfs_bmap *bmap, | |||
284 | 264 | ||
285 | dat = nilfs_bmap_get_dat(bmap); | 265 | dat = nilfs_bmap_get_dat(bmap); |
286 | key = nilfs_bmap_data_get_key(bmap, bh); | 266 | key = nilfs_bmap_data_get_key(bmap, bh); |
287 | ptr = nilfs_direct_get_ptr(direct, key); | 267 | ptr = nilfs_direct_get_ptr(bmap, key); |
288 | if (!buffer_nilfs_volatile(bh)) { | 268 | if (!buffer_nilfs_volatile(bh)) { |
289 | oldreq.pr_entry_nr = ptr; | 269 | oldreq.pr_entry_nr = ptr; |
290 | newreq.pr_entry_nr = ptr; | 270 | newreq.pr_entry_nr = ptr; |
@@ -294,20 +274,20 @@ static int nilfs_direct_propagate(const struct nilfs_bmap *bmap, | |||
294 | nilfs_dat_commit_update(dat, &oldreq, &newreq, | 274 | nilfs_dat_commit_update(dat, &oldreq, &newreq, |
295 | bmap->b_ptr_type == NILFS_BMAP_PTR_VS); | 275 | bmap->b_ptr_type == NILFS_BMAP_PTR_VS); |
296 | set_buffer_nilfs_volatile(bh); | 276 | set_buffer_nilfs_volatile(bh); |
297 | nilfs_direct_set_ptr(direct, key, newreq.pr_entry_nr); | 277 | nilfs_direct_set_ptr(bmap, key, newreq.pr_entry_nr); |
298 | } else | 278 | } else |
299 | ret = nilfs_dat_mark_dirty(dat, ptr); | 279 | ret = nilfs_dat_mark_dirty(dat, ptr); |
300 | 280 | ||
301 | return ret; | 281 | return ret; |
302 | } | 282 | } |
303 | 283 | ||
304 | static int nilfs_direct_assign_v(struct nilfs_direct *direct, | 284 | static int nilfs_direct_assign_v(struct nilfs_bmap *direct, |
305 | __u64 key, __u64 ptr, | 285 | __u64 key, __u64 ptr, |
306 | struct buffer_head **bh, | 286 | struct buffer_head **bh, |
307 | sector_t blocknr, | 287 | sector_t blocknr, |
308 | union nilfs_binfo *binfo) | 288 | union nilfs_binfo *binfo) |
309 | { | 289 | { |
310 | struct inode *dat = nilfs_bmap_get_dat(&direct->d_bmap); | 290 | struct inode *dat = nilfs_bmap_get_dat(direct); |
311 | union nilfs_bmap_ptr_req req; | 291 | union nilfs_bmap_ptr_req req; |
312 | int ret; | 292 | int ret; |
313 | 293 | ||
@@ -315,13 +295,13 @@ static int nilfs_direct_assign_v(struct nilfs_direct *direct, | |||
315 | ret = nilfs_dat_prepare_start(dat, &req.bpr_req); | 295 | ret = nilfs_dat_prepare_start(dat, &req.bpr_req); |
316 | if (!ret) { | 296 | if (!ret) { |
317 | nilfs_dat_commit_start(dat, &req.bpr_req, blocknr); | 297 | nilfs_dat_commit_start(dat, &req.bpr_req, blocknr); |
318 | binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr); | 298 | binfo->bi_v.bi_vblocknr = cpu_to_le64(ptr); |
319 | binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 299 | binfo->bi_v.bi_blkoff = cpu_to_le64(key); |
320 | } | 300 | } |
321 | return ret; | 301 | return ret; |
322 | } | 302 | } |
323 | 303 | ||
324 | static int nilfs_direct_assign_p(struct nilfs_direct *direct, | 304 | static int nilfs_direct_assign_p(struct nilfs_bmap *direct, |
325 | __u64 key, __u64 ptr, | 305 | __u64 key, __u64 ptr, |
326 | struct buffer_head **bh, | 306 | struct buffer_head **bh, |
327 | sector_t blocknr, | 307 | sector_t blocknr, |
@@ -329,7 +309,7 @@ static int nilfs_direct_assign_p(struct nilfs_direct *direct, | |||
329 | { | 309 | { |
330 | nilfs_direct_set_ptr(direct, key, blocknr); | 310 | nilfs_direct_set_ptr(direct, key, blocknr); |
331 | 311 | ||
332 | binfo->bi_dat.bi_blkoff = nilfs_bmap_key_to_dkey(key); | 312 | binfo->bi_dat.bi_blkoff = cpu_to_le64(key); |
333 | binfo->bi_dat.bi_level = 0; | 313 | binfo->bi_dat.bi_level = 0; |
334 | 314 | ||
335 | return 0; | 315 | return 0; |
@@ -340,18 +320,16 @@ static int nilfs_direct_assign(struct nilfs_bmap *bmap, | |||
340 | sector_t blocknr, | 320 | sector_t blocknr, |
341 | union nilfs_binfo *binfo) | 321 | union nilfs_binfo *binfo) |
342 | { | 322 | { |
343 | struct nilfs_direct *direct; | ||
344 | __u64 key; | 323 | __u64 key; |
345 | __u64 ptr; | 324 | __u64 ptr; |
346 | 325 | ||
347 | direct = (struct nilfs_direct *)bmap; | ||
348 | key = nilfs_bmap_data_get_key(bmap, *bh); | 326 | key = nilfs_bmap_data_get_key(bmap, *bh); |
349 | if (unlikely(key > NILFS_DIRECT_KEY_MAX)) { | 327 | if (unlikely(key > NILFS_DIRECT_KEY_MAX)) { |
350 | printk(KERN_CRIT "%s: invalid key: %llu\n", __func__, | 328 | printk(KERN_CRIT "%s: invalid key: %llu\n", __func__, |
351 | (unsigned long long)key); | 329 | (unsigned long long)key); |
352 | return -EINVAL; | 330 | return -EINVAL; |
353 | } | 331 | } |
354 | ptr = nilfs_direct_get_ptr(direct, key); | 332 | ptr = nilfs_direct_get_ptr(bmap, key); |
355 | if (unlikely(ptr == NILFS_BMAP_INVALID_PTR)) { | 333 | if (unlikely(ptr == NILFS_BMAP_INVALID_PTR)) { |
356 | printk(KERN_CRIT "%s: invalid pointer: %llu\n", __func__, | 334 | printk(KERN_CRIT "%s: invalid pointer: %llu\n", __func__, |
357 | (unsigned long long)ptr); | 335 | (unsigned long long)ptr); |
@@ -359,8 +337,8 @@ static int nilfs_direct_assign(struct nilfs_bmap *bmap, | |||
359 | } | 337 | } |
360 | 338 | ||
361 | return NILFS_BMAP_USE_VBN(bmap) ? | 339 | return NILFS_BMAP_USE_VBN(bmap) ? |
362 | nilfs_direct_assign_v(direct, key, ptr, bh, blocknr, binfo) : | 340 | nilfs_direct_assign_v(bmap, key, ptr, bh, blocknr, binfo) : |
363 | nilfs_direct_assign_p(direct, key, ptr, bh, blocknr, binfo); | 341 | nilfs_direct_assign_p(bmap, key, ptr, bh, blocknr, binfo); |
364 | } | 342 | } |
365 | 343 | ||
366 | static const struct nilfs_bmap_operations nilfs_direct_ops = { | 344 | static const struct nilfs_bmap_operations nilfs_direct_ops = { |
diff --git a/fs/nilfs2/direct.h b/fs/nilfs2/direct.h index a5ffd66e25d0..dc643de20a25 100644 --- a/fs/nilfs2/direct.h +++ b/fs/nilfs2/direct.h | |||
@@ -28,8 +28,6 @@ | |||
28 | #include "bmap.h" | 28 | #include "bmap.h" |
29 | 29 | ||
30 | 30 | ||
31 | struct nilfs_direct; | ||
32 | |||
33 | /** | 31 | /** |
34 | * struct nilfs_direct_node - direct node | 32 | * struct nilfs_direct_node - direct node |
35 | * @dn_flags: flags | 33 | * @dn_flags: flags |
@@ -40,15 +38,6 @@ struct nilfs_direct_node { | |||
40 | __u8 pad[7]; | 38 | __u8 pad[7]; |
41 | }; | 39 | }; |
42 | 40 | ||
43 | /** | ||
44 | * struct nilfs_direct - direct mapping | ||
45 | * @d_bmap: bmap structure | ||
46 | */ | ||
47 | struct nilfs_direct { | ||
48 | struct nilfs_bmap d_bmap; | ||
49 | }; | ||
50 | |||
51 | |||
52 | #define NILFS_DIRECT_NBLOCKS (NILFS_BMAP_SIZE / sizeof(__le64) - 1) | 41 | #define NILFS_DIRECT_NBLOCKS (NILFS_BMAP_SIZE / sizeof(__le64) - 1) |
53 | #define NILFS_DIRECT_KEY_MIN 0 | 42 | #define NILFS_DIRECT_KEY_MIN 0 |
54 | #define NILFS_DIRECT_KEY_MAX (NILFS_DIRECT_NBLOCKS - 1) | 43 | #define NILFS_DIRECT_KEY_MAX (NILFS_DIRECT_NBLOCKS - 1) |
diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c index 145f03cd7d3e..bed3a783129b 100644 --- a/fs/nilfs2/gcinode.c +++ b/fs/nilfs2/gcinode.c | |||
@@ -48,6 +48,8 @@ | |||
48 | #include <linux/slab.h> | 48 | #include <linux/slab.h> |
49 | #include <linux/swap.h> | 49 | #include <linux/swap.h> |
50 | #include "nilfs.h" | 50 | #include "nilfs.h" |
51 | #include "btree.h" | ||
52 | #include "btnode.h" | ||
51 | #include "page.h" | 53 | #include "page.h" |
52 | #include "mdt.h" | 54 | #include "mdt.h" |
53 | #include "dat.h" | 55 | #include "dat.h" |
@@ -149,8 +151,10 @@ int nilfs_gccache_submit_read_data(struct inode *inode, sector_t blkoff, | |||
149 | int nilfs_gccache_submit_read_node(struct inode *inode, sector_t pbn, | 151 | int nilfs_gccache_submit_read_node(struct inode *inode, sector_t pbn, |
150 | __u64 vbn, struct buffer_head **out_bh) | 152 | __u64 vbn, struct buffer_head **out_bh) |
151 | { | 153 | { |
152 | int ret = nilfs_btnode_submit_block(&NILFS_I(inode)->i_btnode_cache, | 154 | int ret; |
153 | vbn ? : pbn, pbn, out_bh); | 155 | |
156 | ret = nilfs_btnode_submit_block(&NILFS_I(inode)->i_btnode_cache, | ||
157 | vbn ? : pbn, pbn, READ, out_bh, &pbn); | ||
154 | if (ret == -EEXIST) /* internal code (cache hit) */ | 158 | if (ret == -EEXIST) /* internal code (cache hit) */ |
155 | ret = 0; | 159 | ret = 0; |
156 | return ret; | 160 | return ret; |
@@ -164,10 +168,15 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh) | |||
164 | if (buffer_dirty(bh)) | 168 | if (buffer_dirty(bh)) |
165 | return -EEXIST; | 169 | return -EEXIST; |
166 | 170 | ||
167 | if (buffer_nilfs_node(bh)) | 171 | if (buffer_nilfs_node(bh)) { |
172 | if (nilfs_btree_broken_node_block(bh)) { | ||
173 | clear_buffer_uptodate(bh); | ||
174 | return -EIO; | ||
175 | } | ||
168 | nilfs_btnode_mark_dirty(bh); | 176 | nilfs_btnode_mark_dirty(bh); |
169 | else | 177 | } else { |
170 | nilfs_mdt_mark_buffer_dirty(bh); | 178 | nilfs_mdt_mark_buffer_dirty(bh); |
179 | } | ||
171 | return 0; | 180 | return 0; |
172 | } | 181 | } |
173 | 182 | ||
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 024be8c35bb6..d01aff4957d9 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/swap.h> | 28 | #include <linux/swap.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include "nilfs.h" | 30 | #include "nilfs.h" |
31 | #include "btnode.h" | ||
31 | #include "segment.h" | 32 | #include "segment.h" |
32 | #include "page.h" | 33 | #include "page.h" |
33 | #include "mdt.h" | 34 | #include "mdt.h" |
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h index 47d6d7928122..0842d775b3e0 100644 --- a/fs/nilfs2/nilfs.h +++ b/fs/nilfs2/nilfs.h | |||
@@ -32,7 +32,6 @@ | |||
32 | #include "the_nilfs.h" | 32 | #include "the_nilfs.h" |
33 | #include "sb.h" | 33 | #include "sb.h" |
34 | #include "bmap.h" | 34 | #include "bmap.h" |
35 | #include "bmap_union.h" | ||
36 | 35 | ||
37 | /* | 36 | /* |
38 | * nilfs inode data in memory | 37 | * nilfs inode data in memory |
@@ -41,7 +40,7 @@ struct nilfs_inode_info { | |||
41 | __u32 i_flags; | 40 | __u32 i_flags; |
42 | unsigned long i_state; /* Dynamic state flags */ | 41 | unsigned long i_state; /* Dynamic state flags */ |
43 | struct nilfs_bmap *i_bmap; | 42 | struct nilfs_bmap *i_bmap; |
44 | union nilfs_bmap_union i_bmap_union; | 43 | struct nilfs_bmap i_bmap_data; |
45 | __u64 i_xattr; /* sector_t ??? */ | 44 | __u64 i_xattr; /* sector_t ??? */ |
46 | __u32 i_dir_start_lookup; | 45 | __u32 i_dir_start_lookup; |
47 | __u64 i_cno; /* check point number for GC inode */ | 46 | __u64 i_cno; /* check point number for GC inode */ |
@@ -71,9 +70,7 @@ static inline struct nilfs_inode_info *NILFS_I(const struct inode *inode) | |||
71 | static inline struct nilfs_inode_info * | 70 | static inline struct nilfs_inode_info * |
72 | NILFS_BMAP_I(const struct nilfs_bmap *bmap) | 71 | NILFS_BMAP_I(const struct nilfs_bmap *bmap) |
73 | { | 72 | { |
74 | return container_of((union nilfs_bmap_union *)bmap, | 73 | return container_of(bmap, struct nilfs_inode_info, i_bmap_data); |
75 | struct nilfs_inode_info, | ||
76 | i_bmap_union); | ||
77 | } | 74 | } |
78 | 75 | ||
79 | static inline struct inode *NILFS_BTNC_I(struct address_space *btnc) | 76 | static inline struct inode *NILFS_BTNC_I(struct address_space *btnc) |
@@ -107,6 +104,14 @@ enum { | |||
107 | }; | 104 | }; |
108 | 105 | ||
109 | /* | 106 | /* |
107 | * commit flags for nilfs_commit_super and nilfs_sync_super | ||
108 | */ | ||
109 | enum { | ||
110 | NILFS_SB_COMMIT = 0, /* Commit a super block alternately */ | ||
111 | NILFS_SB_COMMIT_ALL /* Commit both super blocks */ | ||
112 | }; | ||
113 | |||
114 | /* | ||
110 | * Macros to check inode numbers | 115 | * Macros to check inode numbers |
111 | */ | 116 | */ |
112 | #define NILFS_MDT_INO_BITS \ | 117 | #define NILFS_MDT_INO_BITS \ |
@@ -270,7 +275,14 @@ extern struct nilfs_super_block * | |||
270 | nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **); | 275 | nilfs_read_super_block(struct super_block *, u64, int, struct buffer_head **); |
271 | extern int nilfs_store_magic_and_option(struct super_block *, | 276 | extern int nilfs_store_magic_and_option(struct super_block *, |
272 | struct nilfs_super_block *, char *); | 277 | struct nilfs_super_block *, char *); |
278 | extern int nilfs_check_feature_compatibility(struct super_block *, | ||
279 | struct nilfs_super_block *); | ||
280 | extern void nilfs_set_log_cursor(struct nilfs_super_block *, | ||
281 | struct the_nilfs *); | ||
282 | extern struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *, | ||
283 | int flip); | ||
273 | extern int nilfs_commit_super(struct nilfs_sb_info *, int); | 284 | extern int nilfs_commit_super(struct nilfs_sb_info *, int); |
285 | extern int nilfs_cleanup_super(struct nilfs_sb_info *); | ||
274 | extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64); | 286 | extern int nilfs_attach_checkpoint(struct nilfs_sb_info *, __u64); |
275 | extern void nilfs_detach_checkpoint(struct nilfs_sb_info *); | 287 | extern void nilfs_detach_checkpoint(struct nilfs_sb_info *); |
276 | 288 | ||
diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c index 8de3e1e48130..aab11db2cb08 100644 --- a/fs/nilfs2/page.c +++ b/fs/nilfs2/page.c | |||
@@ -37,7 +37,8 @@ | |||
37 | 37 | ||
38 | #define NILFS_BUFFER_INHERENT_BITS \ | 38 | #define NILFS_BUFFER_INHERENT_BITS \ |
39 | ((1UL << BH_Uptodate) | (1UL << BH_Mapped) | (1UL << BH_NILFS_Node) | \ | 39 | ((1UL << BH_Uptodate) | (1UL << BH_Mapped) | (1UL << BH_NILFS_Node) | \ |
40 | (1UL << BH_NILFS_Volatile) | (1UL << BH_NILFS_Allocated)) | 40 | (1UL << BH_NILFS_Volatile) | (1UL << BH_NILFS_Allocated) | \ |
41 | (1UL << BH_NILFS_Checked)) | ||
41 | 42 | ||
42 | static struct buffer_head * | 43 | static struct buffer_head * |
43 | __nilfs_get_page_block(struct page *page, unsigned long block, pgoff_t index, | 44 | __nilfs_get_page_block(struct page *page, unsigned long block, pgoff_t index, |
@@ -129,6 +130,7 @@ void nilfs_forget_buffer(struct buffer_head *bh) | |||
129 | 130 | ||
130 | lock_buffer(bh); | 131 | lock_buffer(bh); |
131 | clear_buffer_nilfs_volatile(bh); | 132 | clear_buffer_nilfs_volatile(bh); |
133 | clear_buffer_nilfs_checked(bh); | ||
132 | clear_buffer_dirty(bh); | 134 | clear_buffer_dirty(bh); |
133 | if (nilfs_page_buffers_clean(page)) | 135 | if (nilfs_page_buffers_clean(page)) |
134 | __nilfs_clear_page_dirty(page); | 136 | __nilfs_clear_page_dirty(page); |
@@ -480,6 +482,7 @@ void nilfs_clear_dirty_pages(struct address_space *mapping) | |||
480 | lock_buffer(bh); | 482 | lock_buffer(bh); |
481 | clear_buffer_dirty(bh); | 483 | clear_buffer_dirty(bh); |
482 | clear_buffer_nilfs_volatile(bh); | 484 | clear_buffer_nilfs_volatile(bh); |
485 | clear_buffer_nilfs_checked(bh); | ||
483 | clear_buffer_uptodate(bh); | 486 | clear_buffer_uptodate(bh); |
484 | clear_buffer_mapped(bh); | 487 | clear_buffer_mapped(bh); |
485 | unlock_buffer(bh); | 488 | unlock_buffer(bh); |
diff --git a/fs/nilfs2/page.h b/fs/nilfs2/page.h index 8abca4d1c1f8..f53d8da41ed7 100644 --- a/fs/nilfs2/page.h +++ b/fs/nilfs2/page.h | |||
@@ -34,11 +34,13 @@ enum { | |||
34 | BH_NILFS_Allocated = BH_PrivateStart, | 34 | BH_NILFS_Allocated = BH_PrivateStart, |
35 | BH_NILFS_Node, | 35 | BH_NILFS_Node, |
36 | BH_NILFS_Volatile, | 36 | BH_NILFS_Volatile, |
37 | BH_NILFS_Checked, | ||
37 | }; | 38 | }; |
38 | 39 | ||
39 | BUFFER_FNS(NILFS_Allocated, nilfs_allocated) /* nilfs private buffers */ | 40 | BUFFER_FNS(NILFS_Allocated, nilfs_allocated) /* nilfs private buffers */ |
40 | BUFFER_FNS(NILFS_Node, nilfs_node) /* nilfs node buffers */ | 41 | BUFFER_FNS(NILFS_Node, nilfs_node) /* nilfs node buffers */ |
41 | BUFFER_FNS(NILFS_Volatile, nilfs_volatile) | 42 | BUFFER_FNS(NILFS_Volatile, nilfs_volatile) |
43 | BUFFER_FNS(NILFS_Checked, nilfs_checked) /* buffer is verified */ | ||
42 | 44 | ||
43 | 45 | ||
44 | void nilfs_mark_buffer_dirty(struct buffer_head *bh); | 46 | void nilfs_mark_buffer_dirty(struct buffer_head *bh); |
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index bae2a516b4ee..83e3d8c61a01 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c | |||
@@ -91,27 +91,9 @@ static int nilfs_warn_segment_error(int err) | |||
91 | return -EINVAL; | 91 | return -EINVAL; |
92 | } | 92 | } |
93 | 93 | ||
94 | static void store_segsum_info(struct nilfs_segsum_info *ssi, | ||
95 | struct nilfs_segment_summary *sum, | ||
96 | unsigned int blocksize) | ||
97 | { | ||
98 | ssi->flags = le16_to_cpu(sum->ss_flags); | ||
99 | ssi->seg_seq = le64_to_cpu(sum->ss_seq); | ||
100 | ssi->ctime = le64_to_cpu(sum->ss_create); | ||
101 | ssi->next = le64_to_cpu(sum->ss_next); | ||
102 | ssi->nblocks = le32_to_cpu(sum->ss_nblocks); | ||
103 | ssi->nfinfo = le32_to_cpu(sum->ss_nfinfo); | ||
104 | ssi->sumbytes = le32_to_cpu(sum->ss_sumbytes); | ||
105 | |||
106 | ssi->nsumblk = DIV_ROUND_UP(ssi->sumbytes, blocksize); | ||
107 | ssi->nfileblk = ssi->nblocks - ssi->nsumblk - !!NILFS_SEG_HAS_SR(ssi); | ||
108 | |||
109 | /* need to verify ->ss_bytes field if read ->ss_cno */ | ||
110 | } | ||
111 | |||
112 | /** | 94 | /** |
113 | * calc_crc_cont - check CRC of blocks continuously | 95 | * nilfs_compute_checksum - compute checksum of blocks continuously |
114 | * @sbi: nilfs_sb_info | 96 | * @nilfs: nilfs object |
115 | * @bhs: buffer head of start block | 97 | * @bhs: buffer head of start block |
116 | * @sum: place to store result | 98 | * @sum: place to store result |
117 | * @offset: offset bytes in the first block | 99 | * @offset: offset bytes in the first block |
@@ -119,23 +101,25 @@ static void store_segsum_info(struct nilfs_segsum_info *ssi, | |||
119 | * @start: DBN of start block | 101 | * @start: DBN of start block |
120 | * @nblock: number of blocks to be checked | 102 | * @nblock: number of blocks to be checked |
121 | */ | 103 | */ |
122 | static int calc_crc_cont(struct nilfs_sb_info *sbi, struct buffer_head *bhs, | 104 | static int nilfs_compute_checksum(struct the_nilfs *nilfs, |
123 | u32 *sum, unsigned long offset, u64 check_bytes, | 105 | struct buffer_head *bhs, u32 *sum, |
124 | sector_t start, unsigned long nblock) | 106 | unsigned long offset, u64 check_bytes, |
107 | sector_t start, unsigned long nblock) | ||
125 | { | 108 | { |
126 | unsigned long blocksize = sbi->s_super->s_blocksize; | 109 | unsigned int blocksize = nilfs->ns_blocksize; |
127 | unsigned long size; | 110 | unsigned long size; |
128 | u32 crc; | 111 | u32 crc; |
129 | 112 | ||
130 | BUG_ON(offset >= blocksize); | 113 | BUG_ON(offset >= blocksize); |
131 | check_bytes -= offset; | 114 | check_bytes -= offset; |
132 | size = min_t(u64, check_bytes, blocksize - offset); | 115 | size = min_t(u64, check_bytes, blocksize - offset); |
133 | crc = crc32_le(sbi->s_nilfs->ns_crc_seed, | 116 | crc = crc32_le(nilfs->ns_crc_seed, |
134 | (unsigned char *)bhs->b_data + offset, size); | 117 | (unsigned char *)bhs->b_data + offset, size); |
135 | if (--nblock > 0) { | 118 | if (--nblock > 0) { |
136 | do { | 119 | do { |
137 | struct buffer_head *bh | 120 | struct buffer_head *bh; |
138 | = sb_bread(sbi->s_super, ++start); | 121 | |
122 | bh = __bread(nilfs->ns_bdev, ++start, blocksize); | ||
139 | if (!bh) | 123 | if (!bh) |
140 | return -EIO; | 124 | return -EIO; |
141 | check_bytes -= size; | 125 | check_bytes -= size; |
@@ -150,12 +134,12 @@ static int calc_crc_cont(struct nilfs_sb_info *sbi, struct buffer_head *bhs, | |||
150 | 134 | ||
151 | /** | 135 | /** |
152 | * nilfs_read_super_root_block - read super root block | 136 | * nilfs_read_super_root_block - read super root block |
153 | * @sb: super_block | 137 | * @nilfs: nilfs object |
154 | * @sr_block: disk block number of the super root block | 138 | * @sr_block: disk block number of the super root block |
155 | * @pbh: address of a buffer_head pointer to return super root buffer | 139 | * @pbh: address of a buffer_head pointer to return super root buffer |
156 | * @check: CRC check flag | 140 | * @check: CRC check flag |
157 | */ | 141 | */ |
158 | int nilfs_read_super_root_block(struct super_block *sb, sector_t sr_block, | 142 | int nilfs_read_super_root_block(struct the_nilfs *nilfs, sector_t sr_block, |
159 | struct buffer_head **pbh, int check) | 143 | struct buffer_head **pbh, int check) |
160 | { | 144 | { |
161 | struct buffer_head *bh_sr; | 145 | struct buffer_head *bh_sr; |
@@ -164,7 +148,7 @@ int nilfs_read_super_root_block(struct super_block *sb, sector_t sr_block, | |||
164 | int ret; | 148 | int ret; |
165 | 149 | ||
166 | *pbh = NULL; | 150 | *pbh = NULL; |
167 | bh_sr = sb_bread(sb, sr_block); | 151 | bh_sr = __bread(nilfs->ns_bdev, sr_block, nilfs->ns_blocksize); |
168 | if (unlikely(!bh_sr)) { | 152 | if (unlikely(!bh_sr)) { |
169 | ret = NILFS_SEG_FAIL_IO; | 153 | ret = NILFS_SEG_FAIL_IO; |
170 | goto failed; | 154 | goto failed; |
@@ -174,12 +158,13 @@ int nilfs_read_super_root_block(struct super_block *sb, sector_t sr_block, | |||
174 | if (check) { | 158 | if (check) { |
175 | unsigned bytes = le16_to_cpu(sr->sr_bytes); | 159 | unsigned bytes = le16_to_cpu(sr->sr_bytes); |
176 | 160 | ||
177 | if (bytes == 0 || bytes > sb->s_blocksize) { | 161 | if (bytes == 0 || bytes > nilfs->ns_blocksize) { |
178 | ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT; | 162 | ret = NILFS_SEG_FAIL_CHECKSUM_SUPER_ROOT; |
179 | goto failed_bh; | 163 | goto failed_bh; |
180 | } | 164 | } |
181 | if (calc_crc_cont(NILFS_SB(sb), bh_sr, &crc, | 165 | if (nilfs_compute_checksum( |
182 | sizeof(sr->sr_sum), bytes, sr_block, 1)) { | 166 | nilfs, bh_sr, &crc, sizeof(sr->sr_sum), bytes, |
167 | sr_block, 1)) { | ||
183 | ret = NILFS_SEG_FAIL_IO; | 168 | ret = NILFS_SEG_FAIL_IO; |
184 | goto failed_bh; | 169 | goto failed_bh; |
185 | } | 170 | } |
@@ -199,64 +184,76 @@ int nilfs_read_super_root_block(struct super_block *sb, sector_t sr_block, | |||
199 | } | 184 | } |
200 | 185 | ||
201 | /** | 186 | /** |
202 | * load_segment_summary - read segment summary of the specified partial segment | 187 | * nilfs_read_log_header - read summary header of the specified log |
203 | * @sbi: nilfs_sb_info | 188 | * @nilfs: nilfs object |
204 | * @pseg_start: start disk block number of partial segment | 189 | * @start_blocknr: start block number of the log |
205 | * @seg_seq: sequence number requested | 190 | * @sum: pointer to return segment summary structure |
206 | * @ssi: pointer to nilfs_segsum_info struct to store information | ||
207 | */ | 191 | */ |
208 | static int | 192 | static struct buffer_head * |
209 | load_segment_summary(struct nilfs_sb_info *sbi, sector_t pseg_start, | 193 | nilfs_read_log_header(struct the_nilfs *nilfs, sector_t start_blocknr, |
210 | u64 seg_seq, struct nilfs_segsum_info *ssi) | 194 | struct nilfs_segment_summary **sum) |
211 | { | 195 | { |
212 | struct buffer_head *bh_sum; | 196 | struct buffer_head *bh_sum; |
213 | struct nilfs_segment_summary *sum; | 197 | |
198 | bh_sum = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize); | ||
199 | if (bh_sum) | ||
200 | *sum = (struct nilfs_segment_summary *)bh_sum->b_data; | ||
201 | return bh_sum; | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * nilfs_validate_log - verify consistency of log | ||
206 | * @nilfs: nilfs object | ||
207 | * @seg_seq: sequence number of segment | ||
208 | * @bh_sum: buffer head of summary block | ||
209 | * @sum: segment summary struct | ||
210 | */ | ||
211 | static int nilfs_validate_log(struct the_nilfs *nilfs, u64 seg_seq, | ||
212 | struct buffer_head *bh_sum, | ||
213 | struct nilfs_segment_summary *sum) | ||
214 | { | ||
214 | unsigned long nblock; | 215 | unsigned long nblock; |
215 | u32 crc; | 216 | u32 crc; |
216 | int ret = NILFS_SEG_FAIL_IO; | 217 | int ret; |
217 | 218 | ||
218 | bh_sum = sb_bread(sbi->s_super, pseg_start); | 219 | ret = NILFS_SEG_FAIL_MAGIC; |
219 | if (!bh_sum) | 220 | if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC) |
220 | goto out; | 221 | goto out; |
221 | 222 | ||
222 | sum = (struct nilfs_segment_summary *)bh_sum->b_data; | 223 | ret = NILFS_SEG_FAIL_SEQ; |
223 | 224 | if (le64_to_cpu(sum->ss_seq) != seg_seq) | |
224 | /* Check consistency of segment summary */ | 225 | goto out; |
225 | if (le32_to_cpu(sum->ss_magic) != NILFS_SEGSUM_MAGIC) { | ||
226 | ret = NILFS_SEG_FAIL_MAGIC; | ||
227 | goto failed; | ||
228 | } | ||
229 | store_segsum_info(ssi, sum, sbi->s_super->s_blocksize); | ||
230 | if (seg_seq != ssi->seg_seq) { | ||
231 | ret = NILFS_SEG_FAIL_SEQ; | ||
232 | goto failed; | ||
233 | } | ||
234 | 226 | ||
235 | nblock = ssi->nblocks; | 227 | nblock = le32_to_cpu(sum->ss_nblocks); |
236 | if (unlikely(nblock == 0 || | 228 | ret = NILFS_SEG_FAIL_CONSISTENCY; |
237 | nblock > sbi->s_nilfs->ns_blocks_per_segment)) { | 229 | if (unlikely(nblock == 0 || nblock > nilfs->ns_blocks_per_segment)) |
238 | /* This limits the number of blocks read in the CRC check */ | 230 | /* This limits the number of blocks read in the CRC check */ |
239 | ret = NILFS_SEG_FAIL_CONSISTENCY; | 231 | goto out; |
240 | goto failed; | 232 | |
241 | } | 233 | ret = NILFS_SEG_FAIL_IO; |
242 | if (calc_crc_cont(sbi, bh_sum, &crc, sizeof(sum->ss_datasum), | 234 | if (nilfs_compute_checksum(nilfs, bh_sum, &crc, sizeof(sum->ss_datasum), |
243 | ((u64)nblock << sbi->s_super->s_blocksize_bits), | 235 | ((u64)nblock << nilfs->ns_blocksize_bits), |
244 | pseg_start, nblock)) { | 236 | bh_sum->b_blocknr, nblock)) |
245 | ret = NILFS_SEG_FAIL_IO; | 237 | goto out; |
246 | goto failed; | 238 | |
247 | } | 239 | ret = NILFS_SEG_FAIL_CHECKSUM_FULL; |
248 | if (crc == le32_to_cpu(sum->ss_datasum)) | 240 | if (crc != le32_to_cpu(sum->ss_datasum)) |
249 | ret = 0; | 241 | goto out; |
250 | else | 242 | ret = 0; |
251 | ret = NILFS_SEG_FAIL_CHECKSUM_FULL; | 243 | out: |
252 | failed: | ||
253 | brelse(bh_sum); | ||
254 | out: | ||
255 | return ret; | 244 | return ret; |
256 | } | 245 | } |
257 | 246 | ||
258 | static void *segsum_get(struct super_block *sb, struct buffer_head **pbh, | 247 | /** |
259 | unsigned int *offset, unsigned int bytes) | 248 | * nilfs_read_summary_info - read an item on summary blocks of a log |
249 | * @nilfs: nilfs object | ||
250 | * @pbh: the current buffer head on summary blocks [in, out] | ||
251 | * @offset: the current byte offset on summary blocks [in, out] | ||
252 | * @bytes: byte size of the item to be read | ||
253 | */ | ||
254 | static void *nilfs_read_summary_info(struct the_nilfs *nilfs, | ||
255 | struct buffer_head **pbh, | ||
256 | unsigned int *offset, unsigned int bytes) | ||
260 | { | 257 | { |
261 | void *ptr; | 258 | void *ptr; |
262 | sector_t blocknr; | 259 | sector_t blocknr; |
@@ -265,7 +262,8 @@ static void *segsum_get(struct super_block *sb, struct buffer_head **pbh, | |||
265 | if (bytes > (*pbh)->b_size - *offset) { | 262 | if (bytes > (*pbh)->b_size - *offset) { |
266 | blocknr = (*pbh)->b_blocknr; | 263 | blocknr = (*pbh)->b_blocknr; |
267 | brelse(*pbh); | 264 | brelse(*pbh); |
268 | *pbh = sb_bread(sb, blocknr + 1); | 265 | *pbh = __bread(nilfs->ns_bdev, blocknr + 1, |
266 | nilfs->ns_blocksize); | ||
269 | if (unlikely(!*pbh)) | 267 | if (unlikely(!*pbh)) |
270 | return NULL; | 268 | return NULL; |
271 | *offset = 0; | 269 | *offset = 0; |
@@ -275,9 +273,18 @@ static void *segsum_get(struct super_block *sb, struct buffer_head **pbh, | |||
275 | return ptr; | 273 | return ptr; |
276 | } | 274 | } |
277 | 275 | ||
278 | static void segsum_skip(struct super_block *sb, struct buffer_head **pbh, | 276 | /** |
279 | unsigned int *offset, unsigned int bytes, | 277 | * nilfs_skip_summary_info - skip items on summary blocks of a log |
280 | unsigned long count) | 278 | * @nilfs: nilfs object |
279 | * @pbh: the current buffer head on summary blocks [in, out] | ||
280 | * @offset: the current byte offset on summary blocks [in, out] | ||
281 | * @bytes: byte size of the item to be skipped | ||
282 | * @count: number of items to be skipped | ||
283 | */ | ||
284 | static void nilfs_skip_summary_info(struct the_nilfs *nilfs, | ||
285 | struct buffer_head **pbh, | ||
286 | unsigned int *offset, unsigned int bytes, | ||
287 | unsigned long count) | ||
281 | { | 288 | { |
282 | unsigned int rest_item_in_current_block | 289 | unsigned int rest_item_in_current_block |
283 | = ((*pbh)->b_size - *offset) / bytes; | 290 | = ((*pbh)->b_size - *offset) / bytes; |
@@ -294,36 +301,46 @@ static void segsum_skip(struct super_block *sb, struct buffer_head **pbh, | |||
294 | *offset = bytes * (count - (bcnt - 1) * nitem_per_block); | 301 | *offset = bytes * (count - (bcnt - 1) * nitem_per_block); |
295 | 302 | ||
296 | brelse(*pbh); | 303 | brelse(*pbh); |
297 | *pbh = sb_bread(sb, blocknr + bcnt); | 304 | *pbh = __bread(nilfs->ns_bdev, blocknr + bcnt, |
305 | nilfs->ns_blocksize); | ||
298 | } | 306 | } |
299 | } | 307 | } |
300 | 308 | ||
301 | static int | 309 | /** |
302 | collect_blocks_from_segsum(struct nilfs_sb_info *sbi, sector_t sum_blocknr, | 310 | * nilfs_scan_dsync_log - get block information of a log written for data sync |
303 | struct nilfs_segsum_info *ssi, | 311 | * @nilfs: nilfs object |
304 | struct list_head *head) | 312 | * @start_blocknr: start block number of the log |
313 | * @sum: log summary information | ||
314 | * @head: list head to add nilfs_recovery_block struct | ||
315 | */ | ||
316 | static int nilfs_scan_dsync_log(struct the_nilfs *nilfs, sector_t start_blocknr, | ||
317 | struct nilfs_segment_summary *sum, | ||
318 | struct list_head *head) | ||
305 | { | 319 | { |
306 | struct buffer_head *bh; | 320 | struct buffer_head *bh; |
307 | unsigned int offset; | 321 | unsigned int offset; |
308 | unsigned long nfinfo = ssi->nfinfo; | 322 | u32 nfinfo, sumbytes; |
309 | sector_t blocknr = sum_blocknr + ssi->nsumblk; | 323 | sector_t blocknr; |
310 | ino_t ino; | 324 | ino_t ino; |
311 | int err = -EIO; | 325 | int err = -EIO; |
312 | 326 | ||
327 | nfinfo = le32_to_cpu(sum->ss_nfinfo); | ||
313 | if (!nfinfo) | 328 | if (!nfinfo) |
314 | return 0; | 329 | return 0; |
315 | 330 | ||
316 | bh = sb_bread(sbi->s_super, sum_blocknr); | 331 | sumbytes = le32_to_cpu(sum->ss_sumbytes); |
332 | blocknr = start_blocknr + DIV_ROUND_UP(sumbytes, nilfs->ns_blocksize); | ||
333 | bh = __bread(nilfs->ns_bdev, start_blocknr, nilfs->ns_blocksize); | ||
317 | if (unlikely(!bh)) | 334 | if (unlikely(!bh)) |
318 | goto out; | 335 | goto out; |
319 | 336 | ||
320 | offset = le16_to_cpu( | 337 | offset = le16_to_cpu(sum->ss_bytes); |
321 | ((struct nilfs_segment_summary *)bh->b_data)->ss_bytes); | ||
322 | for (;;) { | 338 | for (;;) { |
323 | unsigned long nblocks, ndatablk, nnodeblk; | 339 | unsigned long nblocks, ndatablk, nnodeblk; |
324 | struct nilfs_finfo *finfo; | 340 | struct nilfs_finfo *finfo; |
325 | 341 | ||
326 | finfo = segsum_get(sbi->s_super, &bh, &offset, sizeof(*finfo)); | 342 | finfo = nilfs_read_summary_info(nilfs, &bh, &offset, |
343 | sizeof(*finfo)); | ||
327 | if (unlikely(!finfo)) | 344 | if (unlikely(!finfo)) |
328 | goto out; | 345 | goto out; |
329 | 346 | ||
@@ -336,8 +353,8 @@ collect_blocks_from_segsum(struct nilfs_sb_info *sbi, sector_t sum_blocknr, | |||
336 | struct nilfs_recovery_block *rb; | 353 | struct nilfs_recovery_block *rb; |
337 | struct nilfs_binfo_v *binfo; | 354 | struct nilfs_binfo_v *binfo; |
338 | 355 | ||
339 | binfo = segsum_get(sbi->s_super, &bh, &offset, | 356 | binfo = nilfs_read_summary_info(nilfs, &bh, &offset, |
340 | sizeof(*binfo)); | 357 | sizeof(*binfo)); |
341 | if (unlikely(!binfo)) | 358 | if (unlikely(!binfo)) |
342 | goto out; | 359 | goto out; |
343 | 360 | ||
@@ -355,9 +372,9 @@ collect_blocks_from_segsum(struct nilfs_sb_info *sbi, sector_t sum_blocknr, | |||
355 | } | 372 | } |
356 | if (--nfinfo == 0) | 373 | if (--nfinfo == 0) |
357 | break; | 374 | break; |
358 | blocknr += nnodeblk; /* always 0 for the data sync segments */ | 375 | blocknr += nnodeblk; /* always 0 for data sync logs */ |
359 | segsum_skip(sbi->s_super, &bh, &offset, sizeof(__le64), | 376 | nilfs_skip_summary_info(nilfs, &bh, &offset, sizeof(__le64), |
360 | nnodeblk); | 377 | nnodeblk); |
361 | if (unlikely(!bh)) | 378 | if (unlikely(!bh)) |
362 | goto out; | 379 | goto out; |
363 | } | 380 | } |
@@ -467,14 +484,14 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs, | |||
467 | return err; | 484 | return err; |
468 | } | 485 | } |
469 | 486 | ||
470 | static int nilfs_recovery_copy_block(struct nilfs_sb_info *sbi, | 487 | static int nilfs_recovery_copy_block(struct the_nilfs *nilfs, |
471 | struct nilfs_recovery_block *rb, | 488 | struct nilfs_recovery_block *rb, |
472 | struct page *page) | 489 | struct page *page) |
473 | { | 490 | { |
474 | struct buffer_head *bh_org; | 491 | struct buffer_head *bh_org; |
475 | void *kaddr; | 492 | void *kaddr; |
476 | 493 | ||
477 | bh_org = sb_bread(sbi->s_super, rb->blocknr); | 494 | bh_org = __bread(nilfs->ns_bdev, rb->blocknr, nilfs->ns_blocksize); |
478 | if (unlikely(!bh_org)) | 495 | if (unlikely(!bh_org)) |
479 | return -EIO; | 496 | return -EIO; |
480 | 497 | ||
@@ -485,13 +502,14 @@ static int nilfs_recovery_copy_block(struct nilfs_sb_info *sbi, | |||
485 | return 0; | 502 | return 0; |
486 | } | 503 | } |
487 | 504 | ||
488 | static int recover_dsync_blocks(struct nilfs_sb_info *sbi, | 505 | static int nilfs_recover_dsync_blocks(struct the_nilfs *nilfs, |
489 | struct list_head *head, | 506 | struct nilfs_sb_info *sbi, |
490 | unsigned long *nr_salvaged_blocks) | 507 | struct list_head *head, |
508 | unsigned long *nr_salvaged_blocks) | ||
491 | { | 509 | { |
492 | struct inode *inode; | 510 | struct inode *inode; |
493 | struct nilfs_recovery_block *rb, *n; | 511 | struct nilfs_recovery_block *rb, *n; |
494 | unsigned blocksize = sbi->s_super->s_blocksize; | 512 | unsigned blocksize = nilfs->ns_blocksize; |
495 | struct page *page; | 513 | struct page *page; |
496 | loff_t pos; | 514 | loff_t pos; |
497 | int err = 0, err2 = 0; | 515 | int err = 0, err2 = 0; |
@@ -511,7 +529,7 @@ static int recover_dsync_blocks(struct nilfs_sb_info *sbi, | |||
511 | if (unlikely(err)) | 529 | if (unlikely(err)) |
512 | goto failed_inode; | 530 | goto failed_inode; |
513 | 531 | ||
514 | err = nilfs_recovery_copy_block(sbi, rb, page); | 532 | err = nilfs_recovery_copy_block(nilfs, rb, page); |
515 | if (unlikely(err)) | 533 | if (unlikely(err)) |
516 | goto failed_page; | 534 | goto failed_page; |
517 | 535 | ||
@@ -551,18 +569,20 @@ static int recover_dsync_blocks(struct nilfs_sb_info *sbi, | |||
551 | /** | 569 | /** |
552 | * nilfs_do_roll_forward - salvage logical segments newer than the latest | 570 | * nilfs_do_roll_forward - salvage logical segments newer than the latest |
553 | * checkpoint | 571 | * checkpoint |
572 | * @nilfs: nilfs object | ||
554 | * @sbi: nilfs_sb_info | 573 | * @sbi: nilfs_sb_info |
555 | * @nilfs: the_nilfs | ||
556 | * @ri: pointer to a nilfs_recovery_info | 574 | * @ri: pointer to a nilfs_recovery_info |
557 | */ | 575 | */ |
558 | static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | 576 | static int nilfs_do_roll_forward(struct the_nilfs *nilfs, |
559 | struct nilfs_sb_info *sbi, | 577 | struct nilfs_sb_info *sbi, |
560 | struct nilfs_recovery_info *ri) | 578 | struct nilfs_recovery_info *ri) |
561 | { | 579 | { |
562 | struct nilfs_segsum_info ssi; | 580 | struct buffer_head *bh_sum = NULL; |
581 | struct nilfs_segment_summary *sum; | ||
563 | sector_t pseg_start; | 582 | sector_t pseg_start; |
564 | sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */ | 583 | sector_t seg_start, seg_end; /* Starting/ending DBN of full segment */ |
565 | unsigned long nsalvaged_blocks = 0; | 584 | unsigned long nsalvaged_blocks = 0; |
585 | unsigned int flags; | ||
566 | u64 seg_seq; | 586 | u64 seg_seq; |
567 | __u64 segnum, nextnum = 0; | 587 | __u64 segnum, nextnum = 0; |
568 | int empty_seg = 0; | 588 | int empty_seg = 0; |
@@ -581,8 +601,14 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
581 | nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); | 601 | nilfs_get_segment_range(nilfs, segnum, &seg_start, &seg_end); |
582 | 602 | ||
583 | while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) { | 603 | while (segnum != ri->ri_segnum || pseg_start <= ri->ri_pseg_start) { |
604 | brelse(bh_sum); | ||
605 | bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum); | ||
606 | if (!bh_sum) { | ||
607 | err = -EIO; | ||
608 | goto failed; | ||
609 | } | ||
584 | 610 | ||
585 | ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi); | 611 | ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum); |
586 | if (ret) { | 612 | if (ret) { |
587 | if (ret == NILFS_SEG_FAIL_IO) { | 613 | if (ret == NILFS_SEG_FAIL_IO) { |
588 | err = -EIO; | 614 | err = -EIO; |
@@ -590,33 +616,38 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
590 | } | 616 | } |
591 | goto strayed; | 617 | goto strayed; |
592 | } | 618 | } |
593 | if (unlikely(NILFS_SEG_HAS_SR(&ssi))) | 619 | |
620 | flags = le16_to_cpu(sum->ss_flags); | ||
621 | if (flags & NILFS_SS_SR) | ||
594 | goto confused; | 622 | goto confused; |
595 | 623 | ||
596 | /* Found a valid partial segment; do recovery actions */ | 624 | /* Found a valid partial segment; do recovery actions */ |
597 | nextnum = nilfs_get_segnum_of_block(nilfs, ssi.next); | 625 | nextnum = nilfs_get_segnum_of_block(nilfs, |
626 | le64_to_cpu(sum->ss_next)); | ||
598 | empty_seg = 0; | 627 | empty_seg = 0; |
599 | nilfs->ns_ctime = ssi.ctime; | 628 | nilfs->ns_ctime = le64_to_cpu(sum->ss_create); |
600 | if (!(ssi.flags & NILFS_SS_GC)) | 629 | if (!(flags & NILFS_SS_GC)) |
601 | nilfs->ns_nongc_ctime = ssi.ctime; | 630 | nilfs->ns_nongc_ctime = nilfs->ns_ctime; |
602 | 631 | ||
603 | switch (state) { | 632 | switch (state) { |
604 | case RF_INIT_ST: | 633 | case RF_INIT_ST: |
605 | if (!NILFS_SEG_LOGBGN(&ssi) || !NILFS_SEG_DSYNC(&ssi)) | 634 | if (!(flags & NILFS_SS_LOGBGN) || |
635 | !(flags & NILFS_SS_SYNDT)) | ||
606 | goto try_next_pseg; | 636 | goto try_next_pseg; |
607 | state = RF_DSYNC_ST; | 637 | state = RF_DSYNC_ST; |
608 | /* Fall through */ | 638 | /* Fall through */ |
609 | case RF_DSYNC_ST: | 639 | case RF_DSYNC_ST: |
610 | if (!NILFS_SEG_DSYNC(&ssi)) | 640 | if (!(flags & NILFS_SS_SYNDT)) |
611 | goto confused; | 641 | goto confused; |
612 | 642 | ||
613 | err = collect_blocks_from_segsum( | 643 | err = nilfs_scan_dsync_log(nilfs, pseg_start, sum, |
614 | sbi, pseg_start, &ssi, &dsync_blocks); | 644 | &dsync_blocks); |
615 | if (unlikely(err)) | 645 | if (unlikely(err)) |
616 | goto failed; | 646 | goto failed; |
617 | if (NILFS_SEG_LOGEND(&ssi)) { | 647 | if (flags & NILFS_SS_LOGEND) { |
618 | err = recover_dsync_blocks( | 648 | err = nilfs_recover_dsync_blocks( |
619 | sbi, &dsync_blocks, &nsalvaged_blocks); | 649 | nilfs, sbi, &dsync_blocks, |
650 | &nsalvaged_blocks); | ||
620 | if (unlikely(err)) | 651 | if (unlikely(err)) |
621 | goto failed; | 652 | goto failed; |
622 | state = RF_INIT_ST; | 653 | state = RF_INIT_ST; |
@@ -627,7 +658,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
627 | try_next_pseg: | 658 | try_next_pseg: |
628 | if (pseg_start == ri->ri_lsegs_end) | 659 | if (pseg_start == ri->ri_lsegs_end) |
629 | break; | 660 | break; |
630 | pseg_start += ssi.nblocks; | 661 | pseg_start += le32_to_cpu(sum->ss_nblocks); |
631 | if (pseg_start < seg_end) | 662 | if (pseg_start < seg_end) |
632 | continue; | 663 | continue; |
633 | goto feed_segment; | 664 | goto feed_segment; |
@@ -652,8 +683,9 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
652 | ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; | 683 | ri->ri_need_recovery = NILFS_RECOVERY_ROLLFORWARD_DONE; |
653 | } | 684 | } |
654 | out: | 685 | out: |
686 | brelse(bh_sum); | ||
655 | dispose_recovery_list(&dsync_blocks); | 687 | dispose_recovery_list(&dsync_blocks); |
656 | nilfs_detach_writer(sbi->s_nilfs, sbi); | 688 | nilfs_detach_writer(nilfs, sbi); |
657 | return err; | 689 | return err; |
658 | 690 | ||
659 | confused: | 691 | confused: |
@@ -667,7 +699,6 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, | |||
667 | } | 699 | } |
668 | 700 | ||
669 | static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, | 701 | static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, |
670 | struct nilfs_sb_info *sbi, | ||
671 | struct nilfs_recovery_info *ri) | 702 | struct nilfs_recovery_info *ri) |
672 | { | 703 | { |
673 | struct buffer_head *bh; | 704 | struct buffer_head *bh; |
@@ -677,7 +708,7 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, | |||
677 | nilfs_get_segnum_of_block(nilfs, ri->ri_super_root)) | 708 | nilfs_get_segnum_of_block(nilfs, ri->ri_super_root)) |
678 | return; | 709 | return; |
679 | 710 | ||
680 | bh = sb_getblk(sbi->s_super, ri->ri_lsegs_start); | 711 | bh = __getblk(nilfs->ns_bdev, ri->ri_lsegs_start, nilfs->ns_blocksize); |
681 | BUG_ON(!bh); | 712 | BUG_ON(!bh); |
682 | memset(bh->b_data, 0, bh->b_size); | 713 | memset(bh->b_data, 0, bh->b_size); |
683 | set_buffer_dirty(bh); | 714 | set_buffer_dirty(bh); |
@@ -690,9 +721,8 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, | |||
690 | } | 721 | } |
691 | 722 | ||
692 | /** | 723 | /** |
693 | * nilfs_recover_logical_segments - salvage logical segments written after | 724 | * nilfs_salvage_orphan_logs - salvage logs written after the latest checkpoint |
694 | * the latest super root | 725 | * @nilfs: nilfs object |
695 | * @nilfs: the_nilfs | ||
696 | * @sbi: nilfs_sb_info | 726 | * @sbi: nilfs_sb_info |
697 | * @ri: pointer to a nilfs_recovery_info struct to store search results. | 727 | * @ri: pointer to a nilfs_recovery_info struct to store search results. |
698 | * | 728 | * |
@@ -709,9 +739,9 @@ static void nilfs_finish_roll_forward(struct the_nilfs *nilfs, | |||
709 | * | 739 | * |
710 | * %-ENOMEM - Insufficient memory available. | 740 | * %-ENOMEM - Insufficient memory available. |
711 | */ | 741 | */ |
712 | int nilfs_recover_logical_segments(struct the_nilfs *nilfs, | 742 | int nilfs_salvage_orphan_logs(struct the_nilfs *nilfs, |
713 | struct nilfs_sb_info *sbi, | 743 | struct nilfs_sb_info *sbi, |
714 | struct nilfs_recovery_info *ri) | 744 | struct nilfs_recovery_info *ri) |
715 | { | 745 | { |
716 | int err; | 746 | int err; |
717 | 747 | ||
@@ -751,7 +781,7 @@ int nilfs_recover_logical_segments(struct the_nilfs *nilfs, | |||
751 | goto failed; | 781 | goto failed; |
752 | } | 782 | } |
753 | 783 | ||
754 | nilfs_finish_roll_forward(nilfs, sbi, ri); | 784 | nilfs_finish_roll_forward(nilfs, ri); |
755 | } | 785 | } |
756 | 786 | ||
757 | failed: | 787 | failed: |
@@ -762,7 +792,6 @@ int nilfs_recover_logical_segments(struct the_nilfs *nilfs, | |||
762 | /** | 792 | /** |
763 | * nilfs_search_super_root - search the latest valid super root | 793 | * nilfs_search_super_root - search the latest valid super root |
764 | * @nilfs: the_nilfs | 794 | * @nilfs: the_nilfs |
765 | * @sbi: nilfs_sb_info | ||
766 | * @ri: pointer to a nilfs_recovery_info struct to store search results. | 795 | * @ri: pointer to a nilfs_recovery_info struct to store search results. |
767 | * | 796 | * |
768 | * nilfs_search_super_root() looks for the latest super-root from a partial | 797 | * nilfs_search_super_root() looks for the latest super-root from a partial |
@@ -775,14 +804,19 @@ int nilfs_recover_logical_segments(struct the_nilfs *nilfs, | |||
775 | * %-EINVAL - No valid segment found | 804 | * %-EINVAL - No valid segment found |
776 | * | 805 | * |
777 | * %-EIO - I/O error | 806 | * %-EIO - I/O error |
807 | * | ||
808 | * %-ENOMEM - Insufficient memory available. | ||
778 | */ | 809 | */ |
779 | int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | 810 | int nilfs_search_super_root(struct the_nilfs *nilfs, |
780 | struct nilfs_recovery_info *ri) | 811 | struct nilfs_recovery_info *ri) |
781 | { | 812 | { |
782 | struct nilfs_segsum_info ssi; | 813 | struct buffer_head *bh_sum = NULL; |
814 | struct nilfs_segment_summary *sum; | ||
783 | sector_t pseg_start, pseg_end, sr_pseg_start = 0; | 815 | sector_t pseg_start, pseg_end, sr_pseg_start = 0; |
784 | sector_t seg_start, seg_end; /* range of full segment (block number) */ | 816 | sector_t seg_start, seg_end; /* range of full segment (block number) */ |
785 | sector_t b, end; | 817 | sector_t b, end; |
818 | unsigned long nblocks; | ||
819 | unsigned int flags; | ||
786 | u64 seg_seq; | 820 | u64 seg_seq; |
787 | __u64 segnum, nextnum = 0; | 821 | __u64 segnum, nextnum = 0; |
788 | __u64 cno; | 822 | __u64 cno; |
@@ -801,17 +835,24 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
801 | /* Read ahead segment */ | 835 | /* Read ahead segment */ |
802 | b = seg_start; | 836 | b = seg_start; |
803 | while (b <= seg_end) | 837 | while (b <= seg_end) |
804 | sb_breadahead(sbi->s_super, b++); | 838 | __breadahead(nilfs->ns_bdev, b++, nilfs->ns_blocksize); |
805 | 839 | ||
806 | for (;;) { | 840 | for (;;) { |
807 | /* Load segment summary */ | 841 | brelse(bh_sum); |
808 | ret = load_segment_summary(sbi, pseg_start, seg_seq, &ssi); | 842 | ret = NILFS_SEG_FAIL_IO; |
843 | bh_sum = nilfs_read_log_header(nilfs, pseg_start, &sum); | ||
844 | if (!bh_sum) | ||
845 | goto failed; | ||
846 | |||
847 | ret = nilfs_validate_log(nilfs, seg_seq, bh_sum, sum); | ||
809 | if (ret) { | 848 | if (ret) { |
810 | if (ret == NILFS_SEG_FAIL_IO) | 849 | if (ret == NILFS_SEG_FAIL_IO) |
811 | goto failed; | 850 | goto failed; |
812 | goto strayed; | 851 | goto strayed; |
813 | } | 852 | } |
814 | pseg_end = pseg_start + ssi.nblocks - 1; | 853 | |
854 | nblocks = le32_to_cpu(sum->ss_nblocks); | ||
855 | pseg_end = pseg_start + nblocks - 1; | ||
815 | if (unlikely(pseg_end > seg_end)) { | 856 | if (unlikely(pseg_end > seg_end)) { |
816 | ret = NILFS_SEG_FAIL_CONSISTENCY; | 857 | ret = NILFS_SEG_FAIL_CONSISTENCY; |
817 | goto strayed; | 858 | goto strayed; |
@@ -821,11 +862,13 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
821 | ri->ri_pseg_start = pseg_start; | 862 | ri->ri_pseg_start = pseg_start; |
822 | ri->ri_seq = seg_seq; | 863 | ri->ri_seq = seg_seq; |
823 | ri->ri_segnum = segnum; | 864 | ri->ri_segnum = segnum; |
824 | nextnum = nilfs_get_segnum_of_block(nilfs, ssi.next); | 865 | nextnum = nilfs_get_segnum_of_block(nilfs, |
866 | le64_to_cpu(sum->ss_next)); | ||
825 | ri->ri_nextnum = nextnum; | 867 | ri->ri_nextnum = nextnum; |
826 | empty_seg = 0; | 868 | empty_seg = 0; |
827 | 869 | ||
828 | if (!NILFS_SEG_HAS_SR(&ssi) && !scan_newer) { | 870 | flags = le16_to_cpu(sum->ss_flags); |
871 | if (!(flags & NILFS_SS_SR) && !scan_newer) { | ||
829 | /* This will never happen because a superblock | 872 | /* This will never happen because a superblock |
830 | (last_segment) always points to a pseg | 873 | (last_segment) always points to a pseg |
831 | having a super root. */ | 874 | having a super root. */ |
@@ -836,14 +879,15 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
836 | if (pseg_start == seg_start) { | 879 | if (pseg_start == seg_start) { |
837 | nilfs_get_segment_range(nilfs, nextnum, &b, &end); | 880 | nilfs_get_segment_range(nilfs, nextnum, &b, &end); |
838 | while (b <= end) | 881 | while (b <= end) |
839 | sb_breadahead(sbi->s_super, b++); | 882 | __breadahead(nilfs->ns_bdev, b++, |
883 | nilfs->ns_blocksize); | ||
840 | } | 884 | } |
841 | if (!NILFS_SEG_HAS_SR(&ssi)) { | 885 | if (!(flags & NILFS_SS_SR)) { |
842 | if (!ri->ri_lsegs_start && NILFS_SEG_LOGBGN(&ssi)) { | 886 | if (!ri->ri_lsegs_start && (flags & NILFS_SS_LOGBGN)) { |
843 | ri->ri_lsegs_start = pseg_start; | 887 | ri->ri_lsegs_start = pseg_start; |
844 | ri->ri_lsegs_start_seq = seg_seq; | 888 | ri->ri_lsegs_start_seq = seg_seq; |
845 | } | 889 | } |
846 | if (NILFS_SEG_LOGEND(&ssi)) | 890 | if (flags & NILFS_SS_LOGEND) |
847 | ri->ri_lsegs_end = pseg_start; | 891 | ri->ri_lsegs_end = pseg_start; |
848 | goto try_next_pseg; | 892 | goto try_next_pseg; |
849 | } | 893 | } |
@@ -854,12 +898,12 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
854 | ri->ri_lsegs_start = ri->ri_lsegs_end = 0; | 898 | ri->ri_lsegs_start = ri->ri_lsegs_end = 0; |
855 | 899 | ||
856 | nilfs_dispose_segment_list(&segments); | 900 | nilfs_dispose_segment_list(&segments); |
857 | nilfs->ns_pseg_offset = (sr_pseg_start = pseg_start) | 901 | sr_pseg_start = pseg_start; |
858 | + ssi.nblocks - seg_start; | 902 | nilfs->ns_pseg_offset = pseg_start + nblocks - seg_start; |
859 | nilfs->ns_seg_seq = seg_seq; | 903 | nilfs->ns_seg_seq = seg_seq; |
860 | nilfs->ns_segnum = segnum; | 904 | nilfs->ns_segnum = segnum; |
861 | nilfs->ns_cno = cno; /* nilfs->ns_cno = ri->ri_cno + 1 */ | 905 | nilfs->ns_cno = cno; /* nilfs->ns_cno = ri->ri_cno + 1 */ |
862 | nilfs->ns_ctime = ssi.ctime; | 906 | nilfs->ns_ctime = le64_to_cpu(sum->ss_create); |
863 | nilfs->ns_nextnum = nextnum; | 907 | nilfs->ns_nextnum = nextnum; |
864 | 908 | ||
865 | if (scan_newer) | 909 | if (scan_newer) |
@@ -870,15 +914,9 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
870 | scan_newer = 1; | 914 | scan_newer = 1; |
871 | } | 915 | } |
872 | 916 | ||
873 | /* reset region for roll-forward */ | ||
874 | pseg_start += ssi.nblocks; | ||
875 | if (pseg_start < seg_end) | ||
876 | continue; | ||
877 | goto feed_segment; | ||
878 | |||
879 | try_next_pseg: | 917 | try_next_pseg: |
880 | /* Standing on a course, or met an inconsistent state */ | 918 | /* Standing on a course, or met an inconsistent state */ |
881 | pseg_start += ssi.nblocks; | 919 | pseg_start += nblocks; |
882 | if (pseg_start < seg_end) | 920 | if (pseg_start < seg_end) |
883 | continue; | 921 | continue; |
884 | goto feed_segment; | 922 | goto feed_segment; |
@@ -909,6 +947,7 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
909 | 947 | ||
910 | super_root_found: | 948 | super_root_found: |
911 | /* Updating pointers relating to the latest checkpoint */ | 949 | /* Updating pointers relating to the latest checkpoint */ |
950 | brelse(bh_sum); | ||
912 | list_splice_tail(&segments, &ri->ri_used_segments); | 951 | list_splice_tail(&segments, &ri->ri_used_segments); |
913 | nilfs->ns_last_pseg = sr_pseg_start; | 952 | nilfs->ns_last_pseg = sr_pseg_start; |
914 | nilfs->ns_last_seq = nilfs->ns_seg_seq; | 953 | nilfs->ns_last_seq = nilfs->ns_seg_seq; |
@@ -916,6 +955,7 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, | |||
916 | return 0; | 955 | return 0; |
917 | 956 | ||
918 | failed: | 957 | failed: |
958 | brelse(bh_sum); | ||
919 | nilfs_dispose_segment_list(&segments); | 959 | nilfs_dispose_segment_list(&segments); |
920 | return (ret < 0) ? ret : nilfs_warn_segment_error(ret); | 960 | return (ret < 0) ? ret : nilfs_warn_segment_error(ret); |
921 | } | 961 | } |
diff --git a/fs/nilfs2/segbuf.h b/fs/nilfs2/segbuf.h index 85fbb66455e2..b04f08cc2397 100644 --- a/fs/nilfs2/segbuf.h +++ b/fs/nilfs2/segbuf.h | |||
@@ -54,17 +54,6 @@ struct nilfs_segsum_info { | |||
54 | sector_t next; | 54 | sector_t next; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | /* macro for the flags */ | ||
58 | #define NILFS_SEG_HAS_SR(sum) ((sum)->flags & NILFS_SS_SR) | ||
59 | #define NILFS_SEG_LOGBGN(sum) ((sum)->flags & NILFS_SS_LOGBGN) | ||
60 | #define NILFS_SEG_LOGEND(sum) ((sum)->flags & NILFS_SS_LOGEND) | ||
61 | #define NILFS_SEG_DSYNC(sum) ((sum)->flags & NILFS_SS_SYNDT) | ||
62 | #define NILFS_SEG_SIMPLEX(sum) \ | ||
63 | (((sum)->flags & (NILFS_SS_LOGBGN | NILFS_SS_LOGEND)) == \ | ||
64 | (NILFS_SS_LOGBGN | NILFS_SS_LOGEND)) | ||
65 | |||
66 | #define NILFS_SEG_EMPTY(sum) ((sum)->nblocks == (sum)->nsumblk) | ||
67 | |||
68 | /** | 57 | /** |
69 | * struct nilfs_segment_buffer - Segment buffer | 58 | * struct nilfs_segment_buffer - Segment buffer |
70 | * @sb_super: back pointer to a superblock struct | 59 | * @sb_super: back pointer to a superblock struct |
@@ -141,6 +130,19 @@ int nilfs_segbuf_extend_payload(struct nilfs_segment_buffer *, | |||
141 | struct buffer_head **); | 130 | struct buffer_head **); |
142 | void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer *); | 131 | void nilfs_segbuf_fill_in_segsum(struct nilfs_segment_buffer *); |
143 | 132 | ||
133 | static inline int nilfs_segbuf_simplex(struct nilfs_segment_buffer *segbuf) | ||
134 | { | ||
135 | unsigned int flags = segbuf->sb_sum.flags; | ||
136 | |||
137 | return (flags & (NILFS_SS_LOGBGN | NILFS_SS_LOGEND)) == | ||
138 | (NILFS_SS_LOGBGN | NILFS_SS_LOGEND); | ||
139 | } | ||
140 | |||
141 | static inline int nilfs_segbuf_empty(struct nilfs_segment_buffer *segbuf) | ||
142 | { | ||
143 | return segbuf->sb_sum.nblocks == segbuf->sb_sum.nsumblk; | ||
144 | } | ||
145 | |||
144 | static inline void | 146 | static inline void |
145 | nilfs_segbuf_add_segsum_buffer(struct nilfs_segment_buffer *segbuf, | 147 | nilfs_segbuf_add_segsum_buffer(struct nilfs_segment_buffer *segbuf, |
146 | struct buffer_head *bh) | 148 | struct buffer_head *bh) |
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index c9201649cc49..9fd051a33c4f 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c | |||
@@ -1914,12 +1914,12 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
1914 | } | 1914 | } |
1915 | } | 1915 | } |
1916 | 1916 | ||
1917 | if (!NILFS_SEG_SIMPLEX(&segbuf->sb_sum)) { | 1917 | if (!nilfs_segbuf_simplex(segbuf)) { |
1918 | if (NILFS_SEG_LOGBGN(&segbuf->sb_sum)) { | 1918 | if (segbuf->sb_sum.flags & NILFS_SS_LOGBGN) { |
1919 | set_bit(NILFS_SC_UNCLOSED, &sci->sc_flags); | 1919 | set_bit(NILFS_SC_UNCLOSED, &sci->sc_flags); |
1920 | sci->sc_lseg_stime = jiffies; | 1920 | sci->sc_lseg_stime = jiffies; |
1921 | } | 1921 | } |
1922 | if (NILFS_SEG_LOGEND(&segbuf->sb_sum)) | 1922 | if (segbuf->sb_sum.flags & NILFS_SS_LOGEND) |
1923 | clear_bit(NILFS_SC_UNCLOSED, &sci->sc_flags); | 1923 | clear_bit(NILFS_SC_UNCLOSED, &sci->sc_flags); |
1924 | } | 1924 | } |
1925 | } | 1925 | } |
@@ -1951,7 +1951,6 @@ static void nilfs_segctor_complete_write(struct nilfs_sc_info *sci) | |||
1951 | if (update_sr) { | 1951 | if (update_sr) { |
1952 | nilfs_set_last_segment(nilfs, segbuf->sb_pseg_start, | 1952 | nilfs_set_last_segment(nilfs, segbuf->sb_pseg_start, |
1953 | segbuf->sb_sum.seg_seq, nilfs->ns_cno++); | 1953 | segbuf->sb_sum.seg_seq, nilfs->ns_cno++); |
1954 | set_nilfs_sb_dirty(nilfs); | ||
1955 | 1954 | ||
1956 | clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags); | 1955 | clear_bit(NILFS_SC_HAVE_DELTA, &sci->sc_flags); |
1957 | clear_bit(NILFS_SC_DIRTY, &sci->sc_flags); | 1956 | clear_bit(NILFS_SC_DIRTY, &sci->sc_flags); |
@@ -2082,7 +2081,7 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode) | |||
2082 | 2081 | ||
2083 | /* Avoid empty segment */ | 2082 | /* Avoid empty segment */ |
2084 | if (sci->sc_stage.scnt == NILFS_ST_DONE && | 2083 | if (sci->sc_stage.scnt == NILFS_ST_DONE && |
2085 | NILFS_SEG_EMPTY(&sci->sc_curseg->sb_sum)) { | 2084 | nilfs_segbuf_empty(sci->sc_curseg)) { |
2086 | nilfs_segctor_abort_construction(sci, nilfs, 1); | 2085 | nilfs_segctor_abort_construction(sci, nilfs, 1); |
2087 | goto out; | 2086 | goto out; |
2088 | } | 2087 | } |
@@ -2408,6 +2407,7 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) | |||
2408 | { | 2407 | { |
2409 | struct nilfs_sb_info *sbi = sci->sc_sbi; | 2408 | struct nilfs_sb_info *sbi = sci->sc_sbi; |
2410 | struct the_nilfs *nilfs = sbi->s_nilfs; | 2409 | struct the_nilfs *nilfs = sbi->s_nilfs; |
2410 | struct nilfs_super_block **sbp; | ||
2411 | int err = 0; | 2411 | int err = 0; |
2412 | 2412 | ||
2413 | nilfs_segctor_accept(sci); | 2413 | nilfs_segctor_accept(sci); |
@@ -2423,8 +2423,13 @@ static int nilfs_segctor_construct(struct nilfs_sc_info *sci, int mode) | |||
2423 | if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && | 2423 | if (test_bit(NILFS_SC_SUPER_ROOT, &sci->sc_flags) && |
2424 | nilfs_discontinued(nilfs)) { | 2424 | nilfs_discontinued(nilfs)) { |
2425 | down_write(&nilfs->ns_sem); | 2425 | down_write(&nilfs->ns_sem); |
2426 | err = nilfs_commit_super( | 2426 | err = -EIO; |
2427 | sbi, nilfs_altsb_need_update(nilfs)); | 2427 | sbp = nilfs_prepare_super(sbi, |
2428 | nilfs_sb_will_flip(nilfs)); | ||
2429 | if (likely(sbp)) { | ||
2430 | nilfs_set_log_cursor(sbp[0], nilfs); | ||
2431 | err = nilfs_commit_super(sbi, NILFS_SB_COMMIT); | ||
2432 | } | ||
2428 | up_write(&nilfs->ns_sem); | 2433 | up_write(&nilfs->ns_sem); |
2429 | } | 2434 | } |
2430 | } | 2435 | } |
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h index 01e20dbb217d..17c487bd8152 100644 --- a/fs/nilfs2/segment.h +++ b/fs/nilfs2/segment.h | |||
@@ -234,13 +234,13 @@ extern int nilfs_attach_segment_constructor(struct nilfs_sb_info *); | |||
234 | extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *); | 234 | extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *); |
235 | 235 | ||
236 | /* recovery.c */ | 236 | /* recovery.c */ |
237 | extern int nilfs_read_super_root_block(struct super_block *, sector_t, | 237 | extern int nilfs_read_super_root_block(struct the_nilfs *, sector_t, |
238 | struct buffer_head **, int); | 238 | struct buffer_head **, int); |
239 | extern int nilfs_search_super_root(struct the_nilfs *, struct nilfs_sb_info *, | 239 | extern int nilfs_search_super_root(struct the_nilfs *, |
240 | struct nilfs_recovery_info *); | 240 | struct nilfs_recovery_info *); |
241 | extern int nilfs_recover_logical_segments(struct the_nilfs *, | 241 | extern int nilfs_salvage_orphan_logs(struct the_nilfs *, |
242 | struct nilfs_sb_info *, | 242 | struct nilfs_sb_info *, |
243 | struct nilfs_recovery_info *); | 243 | struct nilfs_recovery_info *); |
244 | extern void nilfs_dispose_segment_list(struct list_head *); | 244 | extern void nilfs_dispose_segment_list(struct list_head *); |
245 | 245 | ||
246 | #endif /* _NILFS_SEGMENT_H */ | 246 | #endif /* _NILFS_SEGMENT_H */ |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 414ef68931cf..26078b3407c9 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -55,6 +55,8 @@ | |||
55 | #include "nilfs.h" | 55 | #include "nilfs.h" |
56 | #include "mdt.h" | 56 | #include "mdt.h" |
57 | #include "alloc.h" | 57 | #include "alloc.h" |
58 | #include "btree.h" | ||
59 | #include "btnode.h" | ||
58 | #include "page.h" | 60 | #include "page.h" |
59 | #include "cpfile.h" | 61 | #include "cpfile.h" |
60 | #include "ifile.h" | 62 | #include "ifile.h" |
@@ -74,6 +76,25 @@ struct kmem_cache *nilfs_btree_path_cache; | |||
74 | 76 | ||
75 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); | 77 | static int nilfs_remount(struct super_block *sb, int *flags, char *data); |
76 | 78 | ||
79 | static void nilfs_set_error(struct nilfs_sb_info *sbi) | ||
80 | { | ||
81 | struct the_nilfs *nilfs = sbi->s_nilfs; | ||
82 | struct nilfs_super_block **sbp; | ||
83 | |||
84 | down_write(&nilfs->ns_sem); | ||
85 | if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { | ||
86 | nilfs->ns_mount_state |= NILFS_ERROR_FS; | ||
87 | sbp = nilfs_prepare_super(sbi, 0); | ||
88 | if (likely(sbp)) { | ||
89 | sbp[0]->s_state |= cpu_to_le16(NILFS_ERROR_FS); | ||
90 | if (sbp[1]) | ||
91 | sbp[1]->s_state |= cpu_to_le16(NILFS_ERROR_FS); | ||
92 | nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); | ||
93 | } | ||
94 | } | ||
95 | up_write(&nilfs->ns_sem); | ||
96 | } | ||
97 | |||
77 | /** | 98 | /** |
78 | * nilfs_error() - report failure condition on a filesystem | 99 | * nilfs_error() - report failure condition on a filesystem |
79 | * | 100 | * |
@@ -99,16 +120,7 @@ void nilfs_error(struct super_block *sb, const char *function, | |||
99 | va_end(args); | 120 | va_end(args); |
100 | 121 | ||
101 | if (!(sb->s_flags & MS_RDONLY)) { | 122 | if (!(sb->s_flags & MS_RDONLY)) { |
102 | struct the_nilfs *nilfs = sbi->s_nilfs; | 123 | nilfs_set_error(sbi); |
103 | |||
104 | down_write(&nilfs->ns_sem); | ||
105 | if (!(nilfs->ns_mount_state & NILFS_ERROR_FS)) { | ||
106 | nilfs->ns_mount_state |= NILFS_ERROR_FS; | ||
107 | nilfs->ns_sbp[0]->s_state |= | ||
108 | cpu_to_le16(NILFS_ERROR_FS); | ||
109 | nilfs_commit_super(sbi, 1); | ||
110 | } | ||
111 | up_write(&nilfs->ns_sem); | ||
112 | 124 | ||
113 | if (nilfs_test_opt(sbi, ERRORS_RO)) { | 125 | if (nilfs_test_opt(sbi, ERRORS_RO)) { |
114 | printk(KERN_CRIT "Remounting filesystem read-only\n"); | 126 | printk(KERN_CRIT "Remounting filesystem read-only\n"); |
@@ -176,7 +188,7 @@ static void nilfs_clear_inode(struct inode *inode) | |||
176 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); | 188 | nilfs_btnode_cache_clear(&ii->i_btnode_cache); |
177 | } | 189 | } |
178 | 190 | ||
179 | static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb) | 191 | static int nilfs_sync_super(struct nilfs_sb_info *sbi, int flag) |
180 | { | 192 | { |
181 | struct the_nilfs *nilfs = sbi->s_nilfs; | 193 | struct the_nilfs *nilfs = sbi->s_nilfs; |
182 | int err; | 194 | int err; |
@@ -202,12 +214,20 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb) | |||
202 | printk(KERN_ERR | 214 | printk(KERN_ERR |
203 | "NILFS: unable to write superblock (err=%d)\n", err); | 215 | "NILFS: unable to write superblock (err=%d)\n", err); |
204 | if (err == -EIO && nilfs->ns_sbh[1]) { | 216 | if (err == -EIO && nilfs->ns_sbh[1]) { |
217 | /* | ||
218 | * sbp[0] points to newer log than sbp[1], | ||
219 | * so copy sbp[0] to sbp[1] to take over sbp[0]. | ||
220 | */ | ||
221 | memcpy(nilfs->ns_sbp[1], nilfs->ns_sbp[0], | ||
222 | nilfs->ns_sbsize); | ||
205 | nilfs_fall_back_super_block(nilfs); | 223 | nilfs_fall_back_super_block(nilfs); |
206 | goto retry; | 224 | goto retry; |
207 | } | 225 | } |
208 | } else { | 226 | } else { |
209 | struct nilfs_super_block *sbp = nilfs->ns_sbp[0]; | 227 | struct nilfs_super_block *sbp = nilfs->ns_sbp[0]; |
210 | 228 | ||
229 | nilfs->ns_sbwcount++; | ||
230 | |||
211 | /* | 231 | /* |
212 | * The latest segment becomes trailable from the position | 232 | * The latest segment becomes trailable from the position |
213 | * written in superblock. | 233 | * written in superblock. |
@@ -216,66 +236,122 @@ static int nilfs_sync_super(struct nilfs_sb_info *sbi, int dupsb) | |||
216 | 236 | ||
217 | /* update GC protection for recent segments */ | 237 | /* update GC protection for recent segments */ |
218 | if (nilfs->ns_sbh[1]) { | 238 | if (nilfs->ns_sbh[1]) { |
219 | sbp = NULL; | 239 | if (flag == NILFS_SB_COMMIT_ALL) { |
220 | if (dupsb) { | ||
221 | set_buffer_dirty(nilfs->ns_sbh[1]); | 240 | set_buffer_dirty(nilfs->ns_sbh[1]); |
222 | if (!sync_dirty_buffer(nilfs->ns_sbh[1])) | 241 | if (sync_dirty_buffer(nilfs->ns_sbh[1]) < 0) |
223 | sbp = nilfs->ns_sbp[1]; | 242 | goto out; |
224 | } | 243 | } |
244 | if (le64_to_cpu(nilfs->ns_sbp[1]->s_last_cno) < | ||
245 | le64_to_cpu(nilfs->ns_sbp[0]->s_last_cno)) | ||
246 | sbp = nilfs->ns_sbp[1]; | ||
225 | } | 247 | } |
226 | if (sbp) { | ||
227 | spin_lock(&nilfs->ns_last_segment_lock); | ||
228 | nilfs->ns_prot_seq = le64_to_cpu(sbp->s_last_seq); | ||
229 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
230 | } | ||
231 | } | ||
232 | 248 | ||
249 | spin_lock(&nilfs->ns_last_segment_lock); | ||
250 | nilfs->ns_prot_seq = le64_to_cpu(sbp->s_last_seq); | ||
251 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
252 | } | ||
253 | out: | ||
233 | return err; | 254 | return err; |
234 | } | 255 | } |
235 | 256 | ||
236 | int nilfs_commit_super(struct nilfs_sb_info *sbi, int dupsb) | 257 | void nilfs_set_log_cursor(struct nilfs_super_block *sbp, |
258 | struct the_nilfs *nilfs) | ||
259 | { | ||
260 | sector_t nfreeblocks; | ||
261 | |||
262 | /* nilfs->ns_sem must be locked by the caller. */ | ||
263 | nilfs_count_free_blocks(nilfs, &nfreeblocks); | ||
264 | sbp->s_free_blocks_count = cpu_to_le64(nfreeblocks); | ||
265 | |||
266 | spin_lock(&nilfs->ns_last_segment_lock); | ||
267 | sbp->s_last_seq = cpu_to_le64(nilfs->ns_last_seq); | ||
268 | sbp->s_last_pseg = cpu_to_le64(nilfs->ns_last_pseg); | ||
269 | sbp->s_last_cno = cpu_to_le64(nilfs->ns_last_cno); | ||
270 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
271 | } | ||
272 | |||
273 | struct nilfs_super_block **nilfs_prepare_super(struct nilfs_sb_info *sbi, | ||
274 | int flip) | ||
237 | { | 275 | { |
238 | struct the_nilfs *nilfs = sbi->s_nilfs; | 276 | struct the_nilfs *nilfs = sbi->s_nilfs; |
239 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | 277 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
240 | sector_t nfreeblocks; | ||
241 | time_t t; | ||
242 | int err; | ||
243 | 278 | ||
244 | /* nilfs->sem must be locked by the caller. */ | 279 | /* nilfs->ns_sem must be locked by the caller. */ |
245 | if (sbp[0]->s_magic != cpu_to_le16(NILFS_SUPER_MAGIC)) { | 280 | if (sbp[0]->s_magic != cpu_to_le16(NILFS_SUPER_MAGIC)) { |
246 | if (sbp[1] && sbp[1]->s_magic == cpu_to_le16(NILFS_SUPER_MAGIC)) | 281 | if (sbp[1] && |
247 | nilfs_swap_super_block(nilfs); | 282 | sbp[1]->s_magic == cpu_to_le16(NILFS_SUPER_MAGIC)) { |
248 | else { | 283 | memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); |
284 | } else { | ||
249 | printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", | 285 | printk(KERN_CRIT "NILFS: superblock broke on dev %s\n", |
250 | sbi->s_super->s_id); | 286 | sbi->s_super->s_id); |
251 | return -EIO; | 287 | return NULL; |
252 | } | 288 | } |
289 | } else if (sbp[1] && | ||
290 | sbp[1]->s_magic != cpu_to_le16(NILFS_SUPER_MAGIC)) { | ||
291 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | ||
253 | } | 292 | } |
254 | err = nilfs_count_free_blocks(nilfs, &nfreeblocks); | ||
255 | if (unlikely(err)) { | ||
256 | printk(KERN_ERR "NILFS: failed to count free blocks\n"); | ||
257 | return err; | ||
258 | } | ||
259 | spin_lock(&nilfs->ns_last_segment_lock); | ||
260 | sbp[0]->s_last_seq = cpu_to_le64(nilfs->ns_last_seq); | ||
261 | sbp[0]->s_last_pseg = cpu_to_le64(nilfs->ns_last_pseg); | ||
262 | sbp[0]->s_last_cno = cpu_to_le64(nilfs->ns_last_cno); | ||
263 | spin_unlock(&nilfs->ns_last_segment_lock); | ||
264 | 293 | ||
294 | if (flip && sbp[1]) | ||
295 | nilfs_swap_super_block(nilfs); | ||
296 | |||
297 | return sbp; | ||
298 | } | ||
299 | |||
300 | int nilfs_commit_super(struct nilfs_sb_info *sbi, int flag) | ||
301 | { | ||
302 | struct the_nilfs *nilfs = sbi->s_nilfs; | ||
303 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | ||
304 | time_t t; | ||
305 | |||
306 | /* nilfs->ns_sem must be locked by the caller. */ | ||
265 | t = get_seconds(); | 307 | t = get_seconds(); |
266 | nilfs->ns_sbwtime[0] = t; | 308 | nilfs->ns_sbwtime = t; |
267 | sbp[0]->s_free_blocks_count = cpu_to_le64(nfreeblocks); | ||
268 | sbp[0]->s_wtime = cpu_to_le64(t); | 309 | sbp[0]->s_wtime = cpu_to_le64(t); |
269 | sbp[0]->s_sum = 0; | 310 | sbp[0]->s_sum = 0; |
270 | sbp[0]->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed, | 311 | sbp[0]->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed, |
271 | (unsigned char *)sbp[0], | 312 | (unsigned char *)sbp[0], |
272 | nilfs->ns_sbsize)); | 313 | nilfs->ns_sbsize)); |
273 | if (dupsb && sbp[1]) { | 314 | if (flag == NILFS_SB_COMMIT_ALL && sbp[1]) { |
274 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | 315 | sbp[1]->s_wtime = sbp[0]->s_wtime; |
275 | nilfs->ns_sbwtime[1] = t; | 316 | sbp[1]->s_sum = 0; |
317 | sbp[1]->s_sum = cpu_to_le32(crc32_le(nilfs->ns_crc_seed, | ||
318 | (unsigned char *)sbp[1], | ||
319 | nilfs->ns_sbsize)); | ||
276 | } | 320 | } |
277 | clear_nilfs_sb_dirty(nilfs); | 321 | clear_nilfs_sb_dirty(nilfs); |
278 | return nilfs_sync_super(sbi, dupsb); | 322 | return nilfs_sync_super(sbi, flag); |
323 | } | ||
324 | |||
325 | /** | ||
326 | * nilfs_cleanup_super() - write filesystem state for cleanup | ||
327 | * @sbi: nilfs_sb_info to be unmounted or degraded to read-only | ||
328 | * | ||
329 | * This function restores state flags in the on-disk super block. | ||
330 | * This will set "clean" flag (i.e. NILFS_VALID_FS) unless the | ||
331 | * filesystem was not clean previously. | ||
332 | */ | ||
333 | int nilfs_cleanup_super(struct nilfs_sb_info *sbi) | ||
334 | { | ||
335 | struct nilfs_super_block **sbp; | ||
336 | int flag = NILFS_SB_COMMIT; | ||
337 | int ret = -EIO; | ||
338 | |||
339 | sbp = nilfs_prepare_super(sbi, 0); | ||
340 | if (sbp) { | ||
341 | sbp[0]->s_state = cpu_to_le16(sbi->s_nilfs->ns_mount_state); | ||
342 | nilfs_set_log_cursor(sbp[0], sbi->s_nilfs); | ||
343 | if (sbp[1] && sbp[0]->s_last_cno == sbp[1]->s_last_cno) { | ||
344 | /* | ||
345 | * make the "clean" flag also to the opposite | ||
346 | * super block if both super blocks point to | ||
347 | * the same checkpoint. | ||
348 | */ | ||
349 | sbp[1]->s_state = sbp[0]->s_state; | ||
350 | flag = NILFS_SB_COMMIT_ALL; | ||
351 | } | ||
352 | ret = nilfs_commit_super(sbi, flag); | ||
353 | } | ||
354 | return ret; | ||
279 | } | 355 | } |
280 | 356 | ||
281 | static void nilfs_put_super(struct super_block *sb) | 357 | static void nilfs_put_super(struct super_block *sb) |
@@ -289,8 +365,7 @@ static void nilfs_put_super(struct super_block *sb) | |||
289 | 365 | ||
290 | if (!(sb->s_flags & MS_RDONLY)) { | 366 | if (!(sb->s_flags & MS_RDONLY)) { |
291 | down_write(&nilfs->ns_sem); | 367 | down_write(&nilfs->ns_sem); |
292 | nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state); | 368 | nilfs_cleanup_super(sbi); |
293 | nilfs_commit_super(sbi, 1); | ||
294 | up_write(&nilfs->ns_sem); | 369 | up_write(&nilfs->ns_sem); |
295 | } | 370 | } |
296 | down_write(&nilfs->ns_super_sem); | 371 | down_write(&nilfs->ns_super_sem); |
@@ -311,6 +386,7 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) | |||
311 | { | 386 | { |
312 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 387 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
313 | struct the_nilfs *nilfs = sbi->s_nilfs; | 388 | struct the_nilfs *nilfs = sbi->s_nilfs; |
389 | struct nilfs_super_block **sbp; | ||
314 | int err = 0; | 390 | int err = 0; |
315 | 391 | ||
316 | /* This function is called when super block should be written back */ | 392 | /* This function is called when super block should be written back */ |
@@ -318,8 +394,13 @@ static int nilfs_sync_fs(struct super_block *sb, int wait) | |||
318 | err = nilfs_construct_segment(sb); | 394 | err = nilfs_construct_segment(sb); |
319 | 395 | ||
320 | down_write(&nilfs->ns_sem); | 396 | down_write(&nilfs->ns_sem); |
321 | if (nilfs_sb_dirty(nilfs)) | 397 | if (nilfs_sb_dirty(nilfs)) { |
322 | nilfs_commit_super(sbi, 1); | 398 | sbp = nilfs_prepare_super(sbi, nilfs_sb_will_flip(nilfs)); |
399 | if (likely(sbp)) { | ||
400 | nilfs_set_log_cursor(sbp[0], nilfs); | ||
401 | nilfs_commit_super(sbi, NILFS_SB_COMMIT); | ||
402 | } | ||
403 | } | ||
323 | up_write(&nilfs->ns_sem); | 404 | up_write(&nilfs->ns_sem); |
324 | 405 | ||
325 | return err; | 406 | return err; |
@@ -442,20 +523,20 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
442 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 523 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
443 | 524 | ||
444 | if (!nilfs_test_opt(sbi, BARRIER)) | 525 | if (!nilfs_test_opt(sbi, BARRIER)) |
445 | seq_printf(seq, ",nobarrier"); | 526 | seq_puts(seq, ",nobarrier"); |
446 | if (nilfs_test_opt(sbi, SNAPSHOT)) | 527 | if (nilfs_test_opt(sbi, SNAPSHOT)) |
447 | seq_printf(seq, ",cp=%llu", | 528 | seq_printf(seq, ",cp=%llu", |
448 | (unsigned long long int)sbi->s_snapshot_cno); | 529 | (unsigned long long int)sbi->s_snapshot_cno); |
449 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) | 530 | if (nilfs_test_opt(sbi, ERRORS_PANIC)) |
450 | seq_printf(seq, ",errors=panic"); | 531 | seq_puts(seq, ",errors=panic"); |
451 | if (nilfs_test_opt(sbi, ERRORS_CONT)) | 532 | if (nilfs_test_opt(sbi, ERRORS_CONT)) |
452 | seq_printf(seq, ",errors=continue"); | 533 | seq_puts(seq, ",errors=continue"); |
453 | if (nilfs_test_opt(sbi, STRICT_ORDER)) | 534 | if (nilfs_test_opt(sbi, STRICT_ORDER)) |
454 | seq_printf(seq, ",order=strict"); | 535 | seq_puts(seq, ",order=strict"); |
455 | if (nilfs_test_opt(sbi, NORECOVERY)) | 536 | if (nilfs_test_opt(sbi, NORECOVERY)) |
456 | seq_printf(seq, ",norecovery"); | 537 | seq_puts(seq, ",norecovery"); |
457 | if (nilfs_test_opt(sbi, DISCARD)) | 538 | if (nilfs_test_opt(sbi, DISCARD)) |
458 | seq_printf(seq, ",discard"); | 539 | seq_puts(seq, ",discard"); |
459 | 540 | ||
460 | return 0; | 541 | return 0; |
461 | } | 542 | } |
@@ -524,23 +605,25 @@ static const struct export_operations nilfs_export_ops = { | |||
524 | 605 | ||
525 | enum { | 606 | enum { |
526 | Opt_err_cont, Opt_err_panic, Opt_err_ro, | 607 | Opt_err_cont, Opt_err_panic, Opt_err_ro, |
527 | Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, | 608 | Opt_barrier, Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, |
528 | Opt_discard, Opt_err, | 609 | Opt_discard, Opt_nodiscard, Opt_err, |
529 | }; | 610 | }; |
530 | 611 | ||
531 | static match_table_t tokens = { | 612 | static match_table_t tokens = { |
532 | {Opt_err_cont, "errors=continue"}, | 613 | {Opt_err_cont, "errors=continue"}, |
533 | {Opt_err_panic, "errors=panic"}, | 614 | {Opt_err_panic, "errors=panic"}, |
534 | {Opt_err_ro, "errors=remount-ro"}, | 615 | {Opt_err_ro, "errors=remount-ro"}, |
616 | {Opt_barrier, "barrier"}, | ||
535 | {Opt_nobarrier, "nobarrier"}, | 617 | {Opt_nobarrier, "nobarrier"}, |
536 | {Opt_snapshot, "cp=%u"}, | 618 | {Opt_snapshot, "cp=%u"}, |
537 | {Opt_order, "order=%s"}, | 619 | {Opt_order, "order=%s"}, |
538 | {Opt_norecovery, "norecovery"}, | 620 | {Opt_norecovery, "norecovery"}, |
539 | {Opt_discard, "discard"}, | 621 | {Opt_discard, "discard"}, |
622 | {Opt_nodiscard, "nodiscard"}, | ||
540 | {Opt_err, NULL} | 623 | {Opt_err, NULL} |
541 | }; | 624 | }; |
542 | 625 | ||
543 | static int parse_options(char *options, struct super_block *sb) | 626 | static int parse_options(char *options, struct super_block *sb, int is_remount) |
544 | { | 627 | { |
545 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 628 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
546 | char *p; | 629 | char *p; |
@@ -557,6 +640,9 @@ static int parse_options(char *options, struct super_block *sb) | |||
557 | 640 | ||
558 | token = match_token(p, tokens, args); | 641 | token = match_token(p, tokens, args); |
559 | switch (token) { | 642 | switch (token) { |
643 | case Opt_barrier: | ||
644 | nilfs_set_opt(sbi, BARRIER); | ||
645 | break; | ||
560 | case Opt_nobarrier: | 646 | case Opt_nobarrier: |
561 | nilfs_clear_opt(sbi, BARRIER); | 647 | nilfs_clear_opt(sbi, BARRIER); |
562 | break; | 648 | break; |
@@ -582,8 +668,26 @@ static int parse_options(char *options, struct super_block *sb) | |||
582 | case Opt_snapshot: | 668 | case Opt_snapshot: |
583 | if (match_int(&args[0], &option) || option <= 0) | 669 | if (match_int(&args[0], &option) || option <= 0) |
584 | return 0; | 670 | return 0; |
585 | if (!(sb->s_flags & MS_RDONLY)) | 671 | if (is_remount) { |
672 | if (!nilfs_test_opt(sbi, SNAPSHOT)) { | ||
673 | printk(KERN_ERR | ||
674 | "NILFS: cannot change regular " | ||
675 | "mount to snapshot.\n"); | ||
676 | return 0; | ||
677 | } else if (option != sbi->s_snapshot_cno) { | ||
678 | printk(KERN_ERR | ||
679 | "NILFS: cannot remount to a " | ||
680 | "different snapshot.\n"); | ||
681 | return 0; | ||
682 | } | ||
683 | break; | ||
684 | } | ||
685 | if (!(sb->s_flags & MS_RDONLY)) { | ||
686 | printk(KERN_ERR "NILFS: cannot mount snapshot " | ||
687 | "read/write. A read-only option is " | ||
688 | "required.\n"); | ||
586 | return 0; | 689 | return 0; |
690 | } | ||
587 | sbi->s_snapshot_cno = option; | 691 | sbi->s_snapshot_cno = option; |
588 | nilfs_set_opt(sbi, SNAPSHOT); | 692 | nilfs_set_opt(sbi, SNAPSHOT); |
589 | break; | 693 | break; |
@@ -593,6 +697,9 @@ static int parse_options(char *options, struct super_block *sb) | |||
593 | case Opt_discard: | 697 | case Opt_discard: |
594 | nilfs_set_opt(sbi, DISCARD); | 698 | nilfs_set_opt(sbi, DISCARD); |
595 | break; | 699 | break; |
700 | case Opt_nodiscard: | ||
701 | nilfs_clear_opt(sbi, DISCARD); | ||
702 | break; | ||
596 | default: | 703 | default: |
597 | printk(KERN_ERR | 704 | printk(KERN_ERR |
598 | "NILFS: Unrecognized mount option \"%s\"\n", p); | 705 | "NILFS: Unrecognized mount option \"%s\"\n", p); |
@@ -613,11 +720,18 @@ nilfs_set_default_options(struct nilfs_sb_info *sbi, | |||
613 | static int nilfs_setup_super(struct nilfs_sb_info *sbi) | 720 | static int nilfs_setup_super(struct nilfs_sb_info *sbi) |
614 | { | 721 | { |
615 | struct the_nilfs *nilfs = sbi->s_nilfs; | 722 | struct the_nilfs *nilfs = sbi->s_nilfs; |
616 | struct nilfs_super_block *sbp = nilfs->ns_sbp[0]; | 723 | struct nilfs_super_block **sbp; |
617 | int max_mnt_count = le16_to_cpu(sbp->s_max_mnt_count); | 724 | int max_mnt_count; |
618 | int mnt_count = le16_to_cpu(sbp->s_mnt_count); | 725 | int mnt_count; |
726 | |||
727 | /* nilfs->ns_sem must be locked by the caller. */ | ||
728 | sbp = nilfs_prepare_super(sbi, 0); | ||
729 | if (!sbp) | ||
730 | return -EIO; | ||
731 | |||
732 | max_mnt_count = le16_to_cpu(sbp[0]->s_max_mnt_count); | ||
733 | mnt_count = le16_to_cpu(sbp[0]->s_mnt_count); | ||
619 | 734 | ||
620 | /* nilfs->sem must be locked by the caller. */ | ||
621 | if (nilfs->ns_mount_state & NILFS_ERROR_FS) { | 735 | if (nilfs->ns_mount_state & NILFS_ERROR_FS) { |
622 | printk(KERN_WARNING | 736 | printk(KERN_WARNING |
623 | "NILFS warning: mounting fs with errors\n"); | 737 | "NILFS warning: mounting fs with errors\n"); |
@@ -628,12 +742,15 @@ static int nilfs_setup_super(struct nilfs_sb_info *sbi) | |||
628 | #endif | 742 | #endif |
629 | } | 743 | } |
630 | if (!max_mnt_count) | 744 | if (!max_mnt_count) |
631 | sbp->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); | 745 | sbp[0]->s_max_mnt_count = cpu_to_le16(NILFS_DFL_MAX_MNT_COUNT); |
632 | 746 | ||
633 | sbp->s_mnt_count = cpu_to_le16(mnt_count + 1); | 747 | sbp[0]->s_mnt_count = cpu_to_le16(mnt_count + 1); |
634 | sbp->s_state = cpu_to_le16(le16_to_cpu(sbp->s_state) & ~NILFS_VALID_FS); | 748 | sbp[0]->s_state = |
635 | sbp->s_mtime = cpu_to_le64(get_seconds()); | 749 | cpu_to_le16(le16_to_cpu(sbp[0]->s_state) & ~NILFS_VALID_FS); |
636 | return nilfs_commit_super(sbi, 1); | 750 | sbp[0]->s_mtime = cpu_to_le64(get_seconds()); |
751 | /* synchronize sbp[1] with sbp[0] */ | ||
752 | memcpy(sbp[1], sbp[0], nilfs->ns_sbsize); | ||
753 | return nilfs_commit_super(sbi, NILFS_SB_COMMIT_ALL); | ||
637 | } | 754 | } |
638 | 755 | ||
639 | struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb, | 756 | struct nilfs_super_block *nilfs_read_super_block(struct super_block *sb, |
@@ -670,7 +787,31 @@ int nilfs_store_magic_and_option(struct super_block *sb, | |||
670 | sbi->s_interval = le32_to_cpu(sbp->s_c_interval); | 787 | sbi->s_interval = le32_to_cpu(sbp->s_c_interval); |
671 | sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max); | 788 | sbi->s_watermark = le32_to_cpu(sbp->s_c_block_max); |
672 | 789 | ||
673 | return !parse_options(data, sb) ? -EINVAL : 0 ; | 790 | return !parse_options(data, sb, 0) ? -EINVAL : 0 ; |
791 | } | ||
792 | |||
793 | int nilfs_check_feature_compatibility(struct super_block *sb, | ||
794 | struct nilfs_super_block *sbp) | ||
795 | { | ||
796 | __u64 features; | ||
797 | |||
798 | features = le64_to_cpu(sbp->s_feature_incompat) & | ||
799 | ~NILFS_FEATURE_INCOMPAT_SUPP; | ||
800 | if (features) { | ||
801 | printk(KERN_ERR "NILFS: couldn't mount because of unsupported " | ||
802 | "optional features (%llx)\n", | ||
803 | (unsigned long long)features); | ||
804 | return -EINVAL; | ||
805 | } | ||
806 | features = le64_to_cpu(sbp->s_feature_compat_ro) & | ||
807 | ~NILFS_FEATURE_COMPAT_RO_SUPP; | ||
808 | if (!(sb->s_flags & MS_RDONLY) && features) { | ||
809 | printk(KERN_ERR "NILFS: couldn't mount RDWR because of " | ||
810 | "unsupported optional features (%llx)\n", | ||
811 | (unsigned long long)features); | ||
812 | return -EINVAL; | ||
813 | } | ||
814 | return 0; | ||
674 | } | 815 | } |
675 | 816 | ||
676 | /** | 817 | /** |
@@ -819,7 +960,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent, | |||
819 | static int nilfs_remount(struct super_block *sb, int *flags, char *data) | 960 | static int nilfs_remount(struct super_block *sb, int *flags, char *data) |
820 | { | 961 | { |
821 | struct nilfs_sb_info *sbi = NILFS_SB(sb); | 962 | struct nilfs_sb_info *sbi = NILFS_SB(sb); |
822 | struct nilfs_super_block *sbp; | ||
823 | struct the_nilfs *nilfs = sbi->s_nilfs; | 963 | struct the_nilfs *nilfs = sbi->s_nilfs; |
824 | unsigned long old_sb_flags; | 964 | unsigned long old_sb_flags; |
825 | struct nilfs_mount_options old_opts; | 965 | struct nilfs_mount_options old_opts; |
@@ -833,32 +973,17 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
833 | old_opts.snapshot_cno = sbi->s_snapshot_cno; | 973 | old_opts.snapshot_cno = sbi->s_snapshot_cno; |
834 | was_snapshot = nilfs_test_opt(sbi, SNAPSHOT); | 974 | was_snapshot = nilfs_test_opt(sbi, SNAPSHOT); |
835 | 975 | ||
836 | if (!parse_options(data, sb)) { | 976 | if (!parse_options(data, sb, 1)) { |
837 | err = -EINVAL; | 977 | err = -EINVAL; |
838 | goto restore_opts; | 978 | goto restore_opts; |
839 | } | 979 | } |
840 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); | 980 | sb->s_flags = (sb->s_flags & ~MS_POSIXACL); |
841 | 981 | ||
842 | err = -EINVAL; | 982 | err = -EINVAL; |
843 | if (was_snapshot) { | 983 | if (was_snapshot && !(*flags & MS_RDONLY)) { |
844 | if (!(*flags & MS_RDONLY)) { | 984 | printk(KERN_ERR "NILFS (device %s): cannot remount snapshot " |
845 | printk(KERN_ERR "NILFS (device %s): cannot remount " | 985 | "read/write.\n", sb->s_id); |
846 | "snapshot read/write.\n", | 986 | goto restore_opts; |
847 | sb->s_id); | ||
848 | goto restore_opts; | ||
849 | } else if (sbi->s_snapshot_cno != old_opts.snapshot_cno) { | ||
850 | printk(KERN_ERR "NILFS (device %s): cannot " | ||
851 | "remount to a different snapshot.\n", | ||
852 | sb->s_id); | ||
853 | goto restore_opts; | ||
854 | } | ||
855 | } else { | ||
856 | if (nilfs_test_opt(sbi, SNAPSHOT)) { | ||
857 | printk(KERN_ERR "NILFS (device %s): cannot change " | ||
858 | "a regular mount to a snapshot.\n", | ||
859 | sb->s_id); | ||
860 | goto restore_opts; | ||
861 | } | ||
862 | } | 987 | } |
863 | 988 | ||
864 | if (!nilfs_valid_fs(nilfs)) { | 989 | if (!nilfs_valid_fs(nilfs)) { |
@@ -880,19 +1005,29 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
880 | * the RDONLY flag and then mark the partition as valid again. | 1005 | * the RDONLY flag and then mark the partition as valid again. |
881 | */ | 1006 | */ |
882 | down_write(&nilfs->ns_sem); | 1007 | down_write(&nilfs->ns_sem); |
883 | sbp = nilfs->ns_sbp[0]; | 1008 | nilfs_cleanup_super(sbi); |
884 | if (!(sbp->s_state & le16_to_cpu(NILFS_VALID_FS)) && | ||
885 | (nilfs->ns_mount_state & NILFS_VALID_FS)) | ||
886 | sbp->s_state = cpu_to_le16(nilfs->ns_mount_state); | ||
887 | sbp->s_mtime = cpu_to_le64(get_seconds()); | ||
888 | nilfs_commit_super(sbi, 1); | ||
889 | up_write(&nilfs->ns_sem); | 1009 | up_write(&nilfs->ns_sem); |
890 | } else { | 1010 | } else { |
1011 | __u64 features; | ||
1012 | |||
891 | /* | 1013 | /* |
892 | * Mounting a RDONLY partition read-write, so reread and | 1014 | * Mounting a RDONLY partition read-write, so reread and |
893 | * store the current valid flag. (It may have been changed | 1015 | * store the current valid flag. (It may have been changed |
894 | * by fsck since we originally mounted the partition.) | 1016 | * by fsck since we originally mounted the partition.) |
895 | */ | 1017 | */ |
1018 | down_read(&nilfs->ns_sem); | ||
1019 | features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) & | ||
1020 | ~NILFS_FEATURE_COMPAT_RO_SUPP; | ||
1021 | up_read(&nilfs->ns_sem); | ||
1022 | if (features) { | ||
1023 | printk(KERN_WARNING "NILFS (device %s): couldn't " | ||
1024 | "remount RDWR because of unsupported optional " | ||
1025 | "features (%llx)\n", | ||
1026 | sb->s_id, (unsigned long long)features); | ||
1027 | err = -EROFS; | ||
1028 | goto restore_opts; | ||
1029 | } | ||
1030 | |||
896 | sb->s_flags &= ~MS_RDONLY; | 1031 | sb->s_flags &= ~MS_RDONLY; |
897 | 1032 | ||
898 | err = nilfs_attach_segment_constructor(sbi); | 1033 | err = nilfs_attach_segment_constructor(sbi); |
@@ -1119,7 +1254,7 @@ static void nilfs_inode_init_once(void *obj) | |||
1119 | init_rwsem(&ii->xattr_sem); | 1254 | init_rwsem(&ii->xattr_sem); |
1120 | #endif | 1255 | #endif |
1121 | nilfs_btnode_cache_init_once(&ii->i_btnode_cache); | 1256 | nilfs_btnode_cache_init_once(&ii->i_btnode_cache); |
1122 | ii->i_bmap = (struct nilfs_bmap *)&ii->i_bmap_union; | 1257 | ii->i_bmap = &ii->i_bmap_data; |
1123 | inode_init_once(&ii->vfs_inode); | 1258 | inode_init_once(&ii->vfs_inode); |
1124 | } | 1259 | } |
1125 | 1260 | ||
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 8c1097327abc..37de1f062d81 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
@@ -38,6 +38,8 @@ | |||
38 | static LIST_HEAD(nilfs_objects); | 38 | static LIST_HEAD(nilfs_objects); |
39 | static DEFINE_SPINLOCK(nilfs_lock); | 39 | static DEFINE_SPINLOCK(nilfs_lock); |
40 | 40 | ||
41 | static int nilfs_valid_sb(struct nilfs_super_block *sbp); | ||
42 | |||
41 | void nilfs_set_last_segment(struct the_nilfs *nilfs, | 43 | void nilfs_set_last_segment(struct the_nilfs *nilfs, |
42 | sector_t start_blocknr, u64 seq, __u64 cno) | 44 | sector_t start_blocknr, u64 seq, __u64 cno) |
43 | { | 45 | { |
@@ -45,6 +47,16 @@ void nilfs_set_last_segment(struct the_nilfs *nilfs, | |||
45 | nilfs->ns_last_pseg = start_blocknr; | 47 | nilfs->ns_last_pseg = start_blocknr; |
46 | nilfs->ns_last_seq = seq; | 48 | nilfs->ns_last_seq = seq; |
47 | nilfs->ns_last_cno = cno; | 49 | nilfs->ns_last_cno = cno; |
50 | |||
51 | if (!nilfs_sb_dirty(nilfs)) { | ||
52 | if (nilfs->ns_prev_seq == nilfs->ns_last_seq) | ||
53 | goto stay_cursor; | ||
54 | |||
55 | set_nilfs_sb_dirty(nilfs); | ||
56 | } | ||
57 | nilfs->ns_prev_seq = nilfs->ns_last_seq; | ||
58 | |||
59 | stay_cursor: | ||
48 | spin_unlock(&nilfs->ns_last_segment_lock); | 60 | spin_unlock(&nilfs->ns_last_segment_lock); |
49 | } | 61 | } |
50 | 62 | ||
@@ -159,8 +171,7 @@ void put_nilfs(struct the_nilfs *nilfs) | |||
159 | kfree(nilfs); | 171 | kfree(nilfs); |
160 | } | 172 | } |
161 | 173 | ||
162 | static int nilfs_load_super_root(struct the_nilfs *nilfs, | 174 | static int nilfs_load_super_root(struct the_nilfs *nilfs, sector_t sr_block) |
163 | struct nilfs_sb_info *sbi, sector_t sr_block) | ||
164 | { | 175 | { |
165 | struct buffer_head *bh_sr; | 176 | struct buffer_head *bh_sr; |
166 | struct nilfs_super_root *raw_sr; | 177 | struct nilfs_super_root *raw_sr; |
@@ -169,7 +180,7 @@ static int nilfs_load_super_root(struct the_nilfs *nilfs, | |||
169 | unsigned inode_size; | 180 | unsigned inode_size; |
170 | int err; | 181 | int err; |
171 | 182 | ||
172 | err = nilfs_read_super_root_block(sbi->s_super, sr_block, &bh_sr, 1); | 183 | err = nilfs_read_super_root_block(nilfs, sr_block, &bh_sr, 1); |
173 | if (unlikely(err)) | 184 | if (unlikely(err)) |
174 | return err; | 185 | return err; |
175 | 186 | ||
@@ -248,6 +259,37 @@ static void nilfs_clear_recovery_info(struct nilfs_recovery_info *ri) | |||
248 | } | 259 | } |
249 | 260 | ||
250 | /** | 261 | /** |
262 | * nilfs_store_log_cursor - load log cursor from a super block | ||
263 | * @nilfs: nilfs object | ||
264 | * @sbp: buffer storing super block to be read | ||
265 | * | ||
266 | * nilfs_store_log_cursor() reads the last position of the log | ||
267 | * containing a super root from a given super block, and initializes | ||
268 | * relevant information on the nilfs object preparatory for log | ||
269 | * scanning and recovery. | ||
270 | */ | ||
271 | static int nilfs_store_log_cursor(struct the_nilfs *nilfs, | ||
272 | struct nilfs_super_block *sbp) | ||
273 | { | ||
274 | int ret = 0; | ||
275 | |||
276 | nilfs->ns_last_pseg = le64_to_cpu(sbp->s_last_pseg); | ||
277 | nilfs->ns_last_cno = le64_to_cpu(sbp->s_last_cno); | ||
278 | nilfs->ns_last_seq = le64_to_cpu(sbp->s_last_seq); | ||
279 | |||
280 | nilfs->ns_prev_seq = nilfs->ns_last_seq; | ||
281 | nilfs->ns_seg_seq = nilfs->ns_last_seq; | ||
282 | nilfs->ns_segnum = | ||
283 | nilfs_get_segnum_of_block(nilfs, nilfs->ns_last_pseg); | ||
284 | nilfs->ns_cno = nilfs->ns_last_cno + 1; | ||
285 | if (nilfs->ns_segnum >= nilfs->ns_nsegments) { | ||
286 | printk(KERN_ERR "NILFS invalid last segment number.\n"); | ||
287 | ret = -EINVAL; | ||
288 | } | ||
289 | return ret; | ||
290 | } | ||
291 | |||
292 | /** | ||
251 | * load_nilfs - load and recover the nilfs | 293 | * load_nilfs - load and recover the nilfs |
252 | * @nilfs: the_nilfs structure to be released | 294 | * @nilfs: the_nilfs structure to be released |
253 | * @sbi: nilfs_sb_info used to recover past segment | 295 | * @sbi: nilfs_sb_info used to recover past segment |
@@ -285,13 +327,55 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
285 | 327 | ||
286 | nilfs_init_recovery_info(&ri); | 328 | nilfs_init_recovery_info(&ri); |
287 | 329 | ||
288 | err = nilfs_search_super_root(nilfs, sbi, &ri); | 330 | err = nilfs_search_super_root(nilfs, &ri); |
289 | if (unlikely(err)) { | 331 | if (unlikely(err)) { |
290 | printk(KERN_ERR "NILFS: error searching super root.\n"); | 332 | struct nilfs_super_block **sbp = nilfs->ns_sbp; |
291 | goto failed; | 333 | int blocksize; |
334 | |||
335 | if (err != -EINVAL) | ||
336 | goto scan_error; | ||
337 | |||
338 | if (!nilfs_valid_sb(sbp[1])) { | ||
339 | printk(KERN_WARNING | ||
340 | "NILFS warning: unable to fall back to spare" | ||
341 | "super block\n"); | ||
342 | goto scan_error; | ||
343 | } | ||
344 | printk(KERN_INFO | ||
345 | "NILFS: try rollback from an earlier position\n"); | ||
346 | |||
347 | /* | ||
348 | * restore super block with its spare and reconfigure | ||
349 | * relevant states of the nilfs object. | ||
350 | */ | ||
351 | memcpy(sbp[0], sbp[1], nilfs->ns_sbsize); | ||
352 | nilfs->ns_crc_seed = le32_to_cpu(sbp[0]->s_crc_seed); | ||
353 | nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime); | ||
354 | |||
355 | /* verify consistency between two super blocks */ | ||
356 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp[0]->s_log_block_size); | ||
357 | if (blocksize != nilfs->ns_blocksize) { | ||
358 | printk(KERN_WARNING | ||
359 | "NILFS warning: blocksize differs between " | ||
360 | "two super blocks (%d != %d)\n", | ||
361 | blocksize, nilfs->ns_blocksize); | ||
362 | goto scan_error; | ||
363 | } | ||
364 | |||
365 | err = nilfs_store_log_cursor(nilfs, sbp[0]); | ||
366 | if (err) | ||
367 | goto scan_error; | ||
368 | |||
369 | /* drop clean flag to allow roll-forward and recovery */ | ||
370 | nilfs->ns_mount_state &= ~NILFS_VALID_FS; | ||
371 | valid_fs = 0; | ||
372 | |||
373 | err = nilfs_search_super_root(nilfs, &ri); | ||
374 | if (err) | ||
375 | goto scan_error; | ||
292 | } | 376 | } |
293 | 377 | ||
294 | err = nilfs_load_super_root(nilfs, sbi, ri.ri_super_root); | 378 | err = nilfs_load_super_root(nilfs, ri.ri_super_root); |
295 | if (unlikely(err)) { | 379 | if (unlikely(err)) { |
296 | printk(KERN_ERR "NILFS: error loading super root.\n"); | 380 | printk(KERN_ERR "NILFS: error loading super root.\n"); |
297 | goto failed; | 381 | goto failed; |
@@ -301,11 +385,23 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
301 | goto skip_recovery; | 385 | goto skip_recovery; |
302 | 386 | ||
303 | if (s_flags & MS_RDONLY) { | 387 | if (s_flags & MS_RDONLY) { |
388 | __u64 features; | ||
389 | |||
304 | if (nilfs_test_opt(sbi, NORECOVERY)) { | 390 | if (nilfs_test_opt(sbi, NORECOVERY)) { |
305 | printk(KERN_INFO "NILFS: norecovery option specified. " | 391 | printk(KERN_INFO "NILFS: norecovery option specified. " |
306 | "skipping roll-forward recovery\n"); | 392 | "skipping roll-forward recovery\n"); |
307 | goto skip_recovery; | 393 | goto skip_recovery; |
308 | } | 394 | } |
395 | features = le64_to_cpu(nilfs->ns_sbp[0]->s_feature_compat_ro) & | ||
396 | ~NILFS_FEATURE_COMPAT_RO_SUPP; | ||
397 | if (features) { | ||
398 | printk(KERN_ERR "NILFS: couldn't proceed with " | ||
399 | "recovery because of unsupported optional " | ||
400 | "features (%llx)\n", | ||
401 | (unsigned long long)features); | ||
402 | err = -EROFS; | ||
403 | goto failed_unload; | ||
404 | } | ||
309 | if (really_read_only) { | 405 | if (really_read_only) { |
310 | printk(KERN_ERR "NILFS: write access " | 406 | printk(KERN_ERR "NILFS: write access " |
311 | "unavailable, cannot proceed.\n"); | 407 | "unavailable, cannot proceed.\n"); |
@@ -320,14 +416,13 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
320 | goto failed_unload; | 416 | goto failed_unload; |
321 | } | 417 | } |
322 | 418 | ||
323 | err = nilfs_recover_logical_segments(nilfs, sbi, &ri); | 419 | err = nilfs_salvage_orphan_logs(nilfs, sbi, &ri); |
324 | if (err) | 420 | if (err) |
325 | goto failed_unload; | 421 | goto failed_unload; |
326 | 422 | ||
327 | down_write(&nilfs->ns_sem); | 423 | down_write(&nilfs->ns_sem); |
328 | nilfs->ns_mount_state |= NILFS_VALID_FS; | 424 | nilfs->ns_mount_state |= NILFS_VALID_FS; /* set "clean" flag */ |
329 | nilfs->ns_sbp[0]->s_state = cpu_to_le16(nilfs->ns_mount_state); | 425 | err = nilfs_cleanup_super(sbi); |
330 | err = nilfs_commit_super(sbi, 1); | ||
331 | up_write(&nilfs->ns_sem); | 426 | up_write(&nilfs->ns_sem); |
332 | 427 | ||
333 | if (err) { | 428 | if (err) { |
@@ -343,6 +438,10 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
343 | sbi->s_super->s_flags = s_flags; | 438 | sbi->s_super->s_flags = s_flags; |
344 | return 0; | 439 | return 0; |
345 | 440 | ||
441 | scan_error: | ||
442 | printk(KERN_ERR "NILFS: error searching super root.\n"); | ||
443 | goto failed; | ||
444 | |||
346 | failed_unload: | 445 | failed_unload: |
347 | nilfs_mdt_destroy(nilfs->ns_cpfile); | 446 | nilfs_mdt_destroy(nilfs->ns_cpfile); |
348 | nilfs_mdt_destroy(nilfs->ns_sufile); | 447 | nilfs_mdt_destroy(nilfs->ns_sufile); |
@@ -515,8 +614,8 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs, | |||
515 | nilfs_swap_super_block(nilfs); | 614 | nilfs_swap_super_block(nilfs); |
516 | } | 615 | } |
517 | 616 | ||
518 | nilfs->ns_sbwtime[0] = le64_to_cpu(sbp[0]->s_wtime); | 617 | nilfs->ns_sbwcount = 0; |
519 | nilfs->ns_sbwtime[1] = valid[!swp] ? le64_to_cpu(sbp[1]->s_wtime) : 0; | 618 | nilfs->ns_sbwtime = le64_to_cpu(sbp[0]->s_wtime); |
520 | nilfs->ns_prot_seq = le64_to_cpu(sbp[valid[1] & !swp]->s_last_seq); | 619 | nilfs->ns_prot_seq = le64_to_cpu(sbp[valid[1] & !swp]->s_last_seq); |
521 | *sbpp = sbp[0]; | 620 | *sbpp = sbp[0]; |
522 | return 0; | 621 | return 0; |
@@ -557,6 +656,10 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
557 | if (err) | 656 | if (err) |
558 | goto out; | 657 | goto out; |
559 | 658 | ||
659 | err = nilfs_check_feature_compatibility(sb, sbp); | ||
660 | if (err) | ||
661 | goto out; | ||
662 | |||
560 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); | 663 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); |
561 | if (sb->s_blocksize != blocksize && | 664 | if (sb->s_blocksize != blocksize && |
562 | !sb_set_blocksize(sb, blocksize)) { | 665 | !sb_set_blocksize(sb, blocksize)) { |
@@ -568,7 +671,7 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
568 | goto out; | 671 | goto out; |
569 | } | 672 | } |
570 | 673 | ||
571 | blocksize = sb_min_blocksize(sb, BLOCK_SIZE); | 674 | blocksize = sb_min_blocksize(sb, NILFS_MIN_BLOCK_SIZE); |
572 | if (!blocksize) { | 675 | if (!blocksize) { |
573 | printk(KERN_ERR "NILFS: unable to set blocksize\n"); | 676 | printk(KERN_ERR "NILFS: unable to set blocksize\n"); |
574 | err = -EINVAL; | 677 | err = -EINVAL; |
@@ -582,7 +685,18 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
582 | if (err) | 685 | if (err) |
583 | goto failed_sbh; | 686 | goto failed_sbh; |
584 | 687 | ||
688 | err = nilfs_check_feature_compatibility(sb, sbp); | ||
689 | if (err) | ||
690 | goto failed_sbh; | ||
691 | |||
585 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); | 692 | blocksize = BLOCK_SIZE << le32_to_cpu(sbp->s_log_block_size); |
693 | if (blocksize < NILFS_MIN_BLOCK_SIZE || | ||
694 | blocksize > NILFS_MAX_BLOCK_SIZE) { | ||
695 | printk(KERN_ERR "NILFS: couldn't mount because of unsupported " | ||
696 | "filesystem blocksize %d\n", blocksize); | ||
697 | err = -EINVAL; | ||
698 | goto failed_sbh; | ||
699 | } | ||
586 | if (sb->s_blocksize != blocksize) { | 700 | if (sb->s_blocksize != blocksize) { |
587 | int hw_blocksize = bdev_logical_block_size(sb->s_bdev); | 701 | int hw_blocksize = bdev_logical_block_size(sb->s_bdev); |
588 | 702 | ||
@@ -604,6 +718,7 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
604 | when reloading fails. */ | 718 | when reloading fails. */ |
605 | } | 719 | } |
606 | nilfs->ns_blocksize_bits = sb->s_blocksize_bits; | 720 | nilfs->ns_blocksize_bits = sb->s_blocksize_bits; |
721 | nilfs->ns_blocksize = blocksize; | ||
607 | 722 | ||
608 | err = nilfs_store_disk_layout(nilfs, sbp); | 723 | err = nilfs_store_disk_layout(nilfs, sbp); |
609 | if (err) | 724 | if (err) |
@@ -616,23 +731,9 @@ int init_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi, char *data) | |||
616 | bdi = nilfs->ns_bdev->bd_inode->i_mapping->backing_dev_info; | 731 | bdi = nilfs->ns_bdev->bd_inode->i_mapping->backing_dev_info; |
617 | nilfs->ns_bdi = bdi ? : &default_backing_dev_info; | 732 | nilfs->ns_bdi = bdi ? : &default_backing_dev_info; |
618 | 733 | ||
619 | /* Finding last segment */ | 734 | err = nilfs_store_log_cursor(nilfs, sbp); |
620 | nilfs->ns_last_pseg = le64_to_cpu(sbp->s_last_pseg); | 735 | if (err) |
621 | nilfs->ns_last_cno = le64_to_cpu(sbp->s_last_cno); | ||
622 | nilfs->ns_last_seq = le64_to_cpu(sbp->s_last_seq); | ||
623 | |||
624 | nilfs->ns_seg_seq = nilfs->ns_last_seq; | ||
625 | nilfs->ns_segnum = | ||
626 | nilfs_get_segnum_of_block(nilfs, nilfs->ns_last_pseg); | ||
627 | nilfs->ns_cno = nilfs->ns_last_cno + 1; | ||
628 | if (nilfs->ns_segnum >= nilfs->ns_nsegments) { | ||
629 | printk(KERN_ERR "NILFS invalid last segment number.\n"); | ||
630 | err = -EINVAL; | ||
631 | goto failed_sbh; | 736 | goto failed_sbh; |
632 | } | ||
633 | /* Dummy values */ | ||
634 | nilfs->ns_free_segments_count = | ||
635 | nilfs->ns_nsegments - (nilfs->ns_segnum + 1); | ||
636 | 737 | ||
637 | /* Initialize gcinode cache */ | 738 | /* Initialize gcinode cache */ |
638 | err = nilfs_init_gccache(nilfs); | 739 | err = nilfs_init_gccache(nilfs); |
diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 1ab974533697..f785a7b0ab99 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h | |||
@@ -57,7 +57,8 @@ enum { | |||
57 | * @ns_current: back pointer to current mount | 57 | * @ns_current: back pointer to current mount |
58 | * @ns_sbh: buffer heads of on-disk super blocks | 58 | * @ns_sbh: buffer heads of on-disk super blocks |
59 | * @ns_sbp: pointers to super block data | 59 | * @ns_sbp: pointers to super block data |
60 | * @ns_sbwtime: previous write time of super blocks | 60 | * @ns_sbwtime: previous write time of super block |
61 | * @ns_sbwcount: write count of super block | ||
61 | * @ns_sbsize: size of valid data in super block | 62 | * @ns_sbsize: size of valid data in super block |
62 | * @ns_supers: list of nilfs super block structs | 63 | * @ns_supers: list of nilfs super block structs |
63 | * @ns_seg_seq: segment sequence counter | 64 | * @ns_seg_seq: segment sequence counter |
@@ -73,7 +74,7 @@ enum { | |||
73 | * @ns_last_seq: sequence value of the latest segment | 74 | * @ns_last_seq: sequence value of the latest segment |
74 | * @ns_last_cno: checkpoint number of the latest segment | 75 | * @ns_last_cno: checkpoint number of the latest segment |
75 | * @ns_prot_seq: least sequence number of segments which must not be reclaimed | 76 | * @ns_prot_seq: least sequence number of segments which must not be reclaimed |
76 | * @ns_free_segments_count: counter of free segments | 77 | * @ns_prev_seq: base sequence number used to decide if advance log cursor |
77 | * @ns_segctor_sem: segment constructor semaphore | 78 | * @ns_segctor_sem: segment constructor semaphore |
78 | * @ns_dat: DAT file inode | 79 | * @ns_dat: DAT file inode |
79 | * @ns_cpfile: checkpoint file inode | 80 | * @ns_cpfile: checkpoint file inode |
@@ -82,6 +83,7 @@ enum { | |||
82 | * @ns_gc_inodes: dummy inodes to keep live blocks | 83 | * @ns_gc_inodes: dummy inodes to keep live blocks |
83 | * @ns_gc_inodes_h: hash list to keep dummy inode holding live blocks | 84 | * @ns_gc_inodes_h: hash list to keep dummy inode holding live blocks |
84 | * @ns_blocksize_bits: bit length of block size | 85 | * @ns_blocksize_bits: bit length of block size |
86 | * @ns_blocksize: block size | ||
85 | * @ns_nsegments: number of segments in filesystem | 87 | * @ns_nsegments: number of segments in filesystem |
86 | * @ns_blocks_per_segment: number of blocks per segment | 88 | * @ns_blocks_per_segment: number of blocks per segment |
87 | * @ns_r_segments_percentage: reserved segments percentage | 89 | * @ns_r_segments_percentage: reserved segments percentage |
@@ -119,7 +121,8 @@ struct the_nilfs { | |||
119 | */ | 121 | */ |
120 | struct buffer_head *ns_sbh[2]; | 122 | struct buffer_head *ns_sbh[2]; |
121 | struct nilfs_super_block *ns_sbp[2]; | 123 | struct nilfs_super_block *ns_sbp[2]; |
122 | time_t ns_sbwtime[2]; | 124 | time_t ns_sbwtime; |
125 | unsigned ns_sbwcount; | ||
123 | unsigned ns_sbsize; | 126 | unsigned ns_sbsize; |
124 | unsigned ns_mount_state; | 127 | unsigned ns_mount_state; |
125 | 128 | ||
@@ -149,7 +152,7 @@ struct the_nilfs { | |||
149 | u64 ns_last_seq; | 152 | u64 ns_last_seq; |
150 | __u64 ns_last_cno; | 153 | __u64 ns_last_cno; |
151 | u64 ns_prot_seq; | 154 | u64 ns_prot_seq; |
152 | unsigned long ns_free_segments_count; | 155 | u64 ns_prev_seq; |
153 | 156 | ||
154 | struct rw_semaphore ns_segctor_sem; | 157 | struct rw_semaphore ns_segctor_sem; |
155 | 158 | ||
@@ -168,6 +171,7 @@ struct the_nilfs { | |||
168 | 171 | ||
169 | /* Disk layout information (static) */ | 172 | /* Disk layout information (static) */ |
170 | unsigned int ns_blocksize_bits; | 173 | unsigned int ns_blocksize_bits; |
174 | unsigned int ns_blocksize; | ||
171 | unsigned long ns_nsegments; | 175 | unsigned long ns_nsegments; |
172 | unsigned long ns_blocks_per_segment; | 176 | unsigned long ns_blocks_per_segment; |
173 | unsigned long ns_r_segments_percentage; | 177 | unsigned long ns_r_segments_percentage; |
@@ -203,20 +207,17 @@ THE_NILFS_FNS(SB_DIRTY, sb_dirty) | |||
203 | 207 | ||
204 | /* Minimum interval of periodical update of superblocks (in seconds) */ | 208 | /* Minimum interval of periodical update of superblocks (in seconds) */ |
205 | #define NILFS_SB_FREQ 10 | 209 | #define NILFS_SB_FREQ 10 |
206 | #define NILFS_ALTSB_FREQ 60 /* spare superblock */ | ||
207 | 210 | ||
208 | static inline int nilfs_sb_need_update(struct the_nilfs *nilfs) | 211 | static inline int nilfs_sb_need_update(struct the_nilfs *nilfs) |
209 | { | 212 | { |
210 | u64 t = get_seconds(); | 213 | u64 t = get_seconds(); |
211 | return t < nilfs->ns_sbwtime[0] || | 214 | return t < nilfs->ns_sbwtime || t > nilfs->ns_sbwtime + NILFS_SB_FREQ; |
212 | t > nilfs->ns_sbwtime[0] + NILFS_SB_FREQ; | ||
213 | } | 215 | } |
214 | 216 | ||
215 | static inline int nilfs_altsb_need_update(struct the_nilfs *nilfs) | 217 | static inline int nilfs_sb_will_flip(struct the_nilfs *nilfs) |
216 | { | 218 | { |
217 | u64 t = get_seconds(); | 219 | int flip_bits = nilfs->ns_sbwcount & 0x0FL; |
218 | struct nilfs_super_block **sbp = nilfs->ns_sbp; | 220 | return (flip_bits != 0x08 && flip_bits != 0x0F); |
219 | return sbp[1] && t > nilfs->ns_sbwtime[1] + NILFS_ALTSB_FREQ; | ||
220 | } | 221 | } |
221 | 222 | ||
222 | void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); | 223 | void nilfs_set_last_segment(struct the_nilfs *, sector_t, u64, __u64); |
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 3623ca20cc18..96337a4fbbdf 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -196,15 +196,14 @@ int ocfs2_get_block(struct inode *inode, sector_t iblock, | |||
196 | dump_stack(); | 196 | dump_stack(); |
197 | goto bail; | 197 | goto bail; |
198 | } | 198 | } |
199 | |||
200 | past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode)); | ||
201 | mlog(0, "Inode %lu, past_eof = %llu\n", inode->i_ino, | ||
202 | (unsigned long long)past_eof); | ||
203 | |||
204 | if (create && (iblock >= past_eof)) | ||
205 | set_buffer_new(bh_result); | ||
206 | } | 199 | } |
207 | 200 | ||
201 | past_eof = ocfs2_blocks_for_bytes(inode->i_sb, i_size_read(inode)); | ||
202 | mlog(0, "Inode %lu, past_eof = %llu\n", inode->i_ino, | ||
203 | (unsigned long long)past_eof); | ||
204 | if (create && (iblock >= past_eof)) | ||
205 | set_buffer_new(bh_result); | ||
206 | |||
208 | bail: | 207 | bail: |
209 | if (err < 0) | 208 | if (err < 0) |
210 | err = -EIO; | 209 | err = -EIO; |
@@ -459,36 +458,6 @@ int walk_page_buffers( handle_t *handle, | |||
459 | return ret; | 458 | return ret; |
460 | } | 459 | } |
461 | 460 | ||
462 | handle_t *ocfs2_start_walk_page_trans(struct inode *inode, | ||
463 | struct page *page, | ||
464 | unsigned from, | ||
465 | unsigned to) | ||
466 | { | ||
467 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
468 | handle_t *handle; | ||
469 | int ret = 0; | ||
470 | |||
471 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | ||
472 | if (IS_ERR(handle)) { | ||
473 | ret = -ENOMEM; | ||
474 | mlog_errno(ret); | ||
475 | goto out; | ||
476 | } | ||
477 | |||
478 | if (ocfs2_should_order_data(inode)) { | ||
479 | ret = ocfs2_jbd2_file_inode(handle, inode); | ||
480 | if (ret < 0) | ||
481 | mlog_errno(ret); | ||
482 | } | ||
483 | out: | ||
484 | if (ret) { | ||
485 | if (!IS_ERR(handle)) | ||
486 | ocfs2_commit_trans(osb, handle); | ||
487 | handle = ERR_PTR(ret); | ||
488 | } | ||
489 | return handle; | ||
490 | } | ||
491 | |||
492 | static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block) | 461 | static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block) |
493 | { | 462 | { |
494 | sector_t status; | 463 | sector_t status; |
@@ -609,7 +578,9 @@ bail: | |||
609 | static void ocfs2_dio_end_io(struct kiocb *iocb, | 578 | static void ocfs2_dio_end_io(struct kiocb *iocb, |
610 | loff_t offset, | 579 | loff_t offset, |
611 | ssize_t bytes, | 580 | ssize_t bytes, |
612 | void *private) | 581 | void *private, |
582 | int ret, | ||
583 | bool is_async) | ||
613 | { | 584 | { |
614 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; | 585 | struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; |
615 | int level; | 586 | int level; |
@@ -623,6 +594,9 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, | |||
623 | if (!level) | 594 | if (!level) |
624 | up_read(&inode->i_alloc_sem); | 595 | up_read(&inode->i_alloc_sem); |
625 | ocfs2_rw_unlock(inode, level); | 596 | ocfs2_rw_unlock(inode, level); |
597 | |||
598 | if (is_async) | ||
599 | aio_complete(iocb, ret, 0); | ||
626 | } | 600 | } |
627 | 601 | ||
628 | /* | 602 | /* |
@@ -1131,23 +1105,37 @@ out: | |||
1131 | */ | 1105 | */ |
1132 | static int ocfs2_grab_pages_for_write(struct address_space *mapping, | 1106 | static int ocfs2_grab_pages_for_write(struct address_space *mapping, |
1133 | struct ocfs2_write_ctxt *wc, | 1107 | struct ocfs2_write_ctxt *wc, |
1134 | u32 cpos, loff_t user_pos, int new, | 1108 | u32 cpos, loff_t user_pos, |
1109 | unsigned user_len, int new, | ||
1135 | struct page *mmap_page) | 1110 | struct page *mmap_page) |
1136 | { | 1111 | { |
1137 | int ret = 0, i; | 1112 | int ret = 0, i; |
1138 | unsigned long start, target_index, index; | 1113 | unsigned long start, target_index, end_index, index; |
1139 | struct inode *inode = mapping->host; | 1114 | struct inode *inode = mapping->host; |
1115 | loff_t last_byte; | ||
1140 | 1116 | ||
1141 | target_index = user_pos >> PAGE_CACHE_SHIFT; | 1117 | target_index = user_pos >> PAGE_CACHE_SHIFT; |
1142 | 1118 | ||
1143 | /* | 1119 | /* |
1144 | * Figure out how many pages we'll be manipulating here. For | 1120 | * Figure out how many pages we'll be manipulating here. For |
1145 | * non allocating write, we just change the one | 1121 | * non allocating write, we just change the one |
1146 | * page. Otherwise, we'll need a whole clusters worth. | 1122 | * page. Otherwise, we'll need a whole clusters worth. If we're |
1123 | * writing past i_size, we only need enough pages to cover the | ||
1124 | * last page of the write. | ||
1147 | */ | 1125 | */ |
1148 | if (new) { | 1126 | if (new) { |
1149 | wc->w_num_pages = ocfs2_pages_per_cluster(inode->i_sb); | 1127 | wc->w_num_pages = ocfs2_pages_per_cluster(inode->i_sb); |
1150 | start = ocfs2_align_clusters_to_page_index(inode->i_sb, cpos); | 1128 | start = ocfs2_align_clusters_to_page_index(inode->i_sb, cpos); |
1129 | /* | ||
1130 | * We need the index *past* the last page we could possibly | ||
1131 | * touch. This is the page past the end of the write or | ||
1132 | * i_size, whichever is greater. | ||
1133 | */ | ||
1134 | last_byte = max(user_pos + user_len, i_size_read(inode)); | ||
1135 | BUG_ON(last_byte < 1); | ||
1136 | end_index = ((last_byte - 1) >> PAGE_CACHE_SHIFT) + 1; | ||
1137 | if ((start + wc->w_num_pages) > end_index) | ||
1138 | wc->w_num_pages = end_index - start; | ||
1151 | } else { | 1139 | } else { |
1152 | wc->w_num_pages = 1; | 1140 | wc->w_num_pages = 1; |
1153 | start = target_index; | 1141 | start = target_index; |
@@ -1620,21 +1608,20 @@ out: | |||
1620 | * write path can treat it as an non-allocating write, which has no | 1608 | * write path can treat it as an non-allocating write, which has no |
1621 | * special case code for sparse/nonsparse files. | 1609 | * special case code for sparse/nonsparse files. |
1622 | */ | 1610 | */ |
1623 | static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos, | 1611 | static int ocfs2_expand_nonsparse_inode(struct inode *inode, |
1624 | unsigned len, | 1612 | struct buffer_head *di_bh, |
1613 | loff_t pos, unsigned len, | ||
1625 | struct ocfs2_write_ctxt *wc) | 1614 | struct ocfs2_write_ctxt *wc) |
1626 | { | 1615 | { |
1627 | int ret; | 1616 | int ret; |
1628 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
1629 | loff_t newsize = pos + len; | 1617 | loff_t newsize = pos + len; |
1630 | 1618 | ||
1631 | if (ocfs2_sparse_alloc(osb)) | 1619 | BUG_ON(ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))); |
1632 | return 0; | ||
1633 | 1620 | ||
1634 | if (newsize <= i_size_read(inode)) | 1621 | if (newsize <= i_size_read(inode)) |
1635 | return 0; | 1622 | return 0; |
1636 | 1623 | ||
1637 | ret = ocfs2_extend_no_holes(inode, newsize, pos); | 1624 | ret = ocfs2_extend_no_holes(inode, di_bh, newsize, pos); |
1638 | if (ret) | 1625 | if (ret) |
1639 | mlog_errno(ret); | 1626 | mlog_errno(ret); |
1640 | 1627 | ||
@@ -1644,6 +1631,18 @@ static int ocfs2_expand_nonsparse_inode(struct inode *inode, loff_t pos, | |||
1644 | return ret; | 1631 | return ret; |
1645 | } | 1632 | } |
1646 | 1633 | ||
1634 | static int ocfs2_zero_tail(struct inode *inode, struct buffer_head *di_bh, | ||
1635 | loff_t pos) | ||
1636 | { | ||
1637 | int ret = 0; | ||
1638 | |||
1639 | BUG_ON(!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))); | ||
1640 | if (pos > i_size_read(inode)) | ||
1641 | ret = ocfs2_zero_extend(inode, di_bh, pos); | ||
1642 | |||
1643 | return ret; | ||
1644 | } | ||
1645 | |||
1647 | int ocfs2_write_begin_nolock(struct address_space *mapping, | 1646 | int ocfs2_write_begin_nolock(struct address_space *mapping, |
1648 | loff_t pos, unsigned len, unsigned flags, | 1647 | loff_t pos, unsigned len, unsigned flags, |
1649 | struct page **pagep, void **fsdata, | 1648 | struct page **pagep, void **fsdata, |
@@ -1679,7 +1678,11 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
1679 | } | 1678 | } |
1680 | } | 1679 | } |
1681 | 1680 | ||
1682 | ret = ocfs2_expand_nonsparse_inode(inode, pos, len, wc); | 1681 | if (ocfs2_sparse_alloc(osb)) |
1682 | ret = ocfs2_zero_tail(inode, di_bh, pos); | ||
1683 | else | ||
1684 | ret = ocfs2_expand_nonsparse_inode(inode, di_bh, pos, len, | ||
1685 | wc); | ||
1683 | if (ret) { | 1686 | if (ret) { |
1684 | mlog_errno(ret); | 1687 | mlog_errno(ret); |
1685 | goto out; | 1688 | goto out; |
@@ -1789,7 +1792,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
1789 | * that we can zero and flush if we error after adding the | 1792 | * that we can zero and flush if we error after adding the |
1790 | * extent. | 1793 | * extent. |
1791 | */ | 1794 | */ |
1792 | ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, | 1795 | ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, len, |
1793 | cluster_of_pages, mmap_page); | 1796 | cluster_of_pages, mmap_page); |
1794 | if (ret) { | 1797 | if (ret) { |
1795 | mlog_errno(ret); | 1798 | mlog_errno(ret); |
diff --git a/fs/ocfs2/dlm/dlmdebug.c b/fs/ocfs2/dlm/dlmdebug.c index 0cd24cf54396..5efdd37dfe48 100644 --- a/fs/ocfs2/dlm/dlmdebug.c +++ b/fs/ocfs2/dlm/dlmdebug.c | |||
@@ -419,7 +419,7 @@ static loff_t debug_buffer_llseek(struct file *file, loff_t off, int whence) | |||
419 | 419 | ||
420 | static int debug_buffer_release(struct inode *inode, struct file *file) | 420 | static int debug_buffer_release(struct inode *inode, struct file *file) |
421 | { | 421 | { |
422 | struct debug_buffer *db = (struct debug_buffer *)file->private_data; | 422 | struct debug_buffer *db = file->private_data; |
423 | 423 | ||
424 | if (db) | 424 | if (db) |
425 | kfree(db->buf); | 425 | kfree(db->buf); |
@@ -715,7 +715,7 @@ static int debug_lockres_open(struct inode *inode, struct file *file) | |||
715 | goto bail; | 715 | goto bail; |
716 | } | 716 | } |
717 | 717 | ||
718 | seq = (struct seq_file *) file->private_data; | 718 | seq = file->private_data; |
719 | seq->private = dl; | 719 | seq->private = dl; |
720 | 720 | ||
721 | dlm_grab(dlm); | 721 | dlm_grab(dlm); |
@@ -731,7 +731,7 @@ bail: | |||
731 | 731 | ||
732 | static int debug_lockres_release(struct inode *inode, struct file *file) | 732 | static int debug_lockres_release(struct inode *inode, struct file *file) |
733 | { | 733 | { |
734 | struct seq_file *seq = (struct seq_file *)file->private_data; | 734 | struct seq_file *seq = file->private_data; |
735 | struct debug_lockres *dl = (struct debug_lockres *)seq->private; | 735 | struct debug_lockres *dl = (struct debug_lockres *)seq->private; |
736 | 736 | ||
737 | if (dl->dl_res) | 737 | if (dl->dl_res) |
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 6b5a492e1749..153abb5abef0 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
@@ -1671,7 +1671,7 @@ struct dlm_ctxt * dlm_register_domain(const char *domain, | |||
1671 | struct dlm_ctxt *dlm = NULL; | 1671 | struct dlm_ctxt *dlm = NULL; |
1672 | struct dlm_ctxt *new_ctxt = NULL; | 1672 | struct dlm_ctxt *new_ctxt = NULL; |
1673 | 1673 | ||
1674 | if (strlen(domain) > O2NM_MAX_NAME_LEN) { | 1674 | if (strlen(domain) >= O2NM_MAX_NAME_LEN) { |
1675 | ret = -ENAMETOOLONG; | 1675 | ret = -ENAMETOOLONG; |
1676 | mlog(ML_ERROR, "domain name length too long\n"); | 1676 | mlog(ML_ERROR, "domain name length too long\n"); |
1677 | goto leave; | 1677 | goto leave; |
@@ -1709,6 +1709,7 @@ retry: | |||
1709 | } | 1709 | } |
1710 | 1710 | ||
1711 | if (dlm_protocol_compare(&dlm->fs_locking_proto, fs_proto)) { | 1711 | if (dlm_protocol_compare(&dlm->fs_locking_proto, fs_proto)) { |
1712 | spin_unlock(&dlm_domain_lock); | ||
1712 | mlog(ML_ERROR, | 1713 | mlog(ML_ERROR, |
1713 | "Requested locking protocol version is not " | 1714 | "Requested locking protocol version is not " |
1714 | "compatible with already registered domain " | 1715 | "compatible with already registered domain " |
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c index 4a7506a4e314..94b97fc6a88e 100644 --- a/fs/ocfs2/dlm/dlmmaster.c +++ b/fs/ocfs2/dlm/dlmmaster.c | |||
@@ -2808,14 +2808,8 @@ again: | |||
2808 | mlog(0, "trying again...\n"); | 2808 | mlog(0, "trying again...\n"); |
2809 | goto again; | 2809 | goto again; |
2810 | } | 2810 | } |
2811 | /* now that we are sure the MIGRATING state is there, drop | ||
2812 | * the unneded state which blocked threads trying to DIRTY */ | ||
2813 | spin_lock(&res->spinlock); | ||
2814 | BUG_ON(!(res->state & DLM_LOCK_RES_BLOCK_DIRTY)); | ||
2815 | BUG_ON(!(res->state & DLM_LOCK_RES_MIGRATING)); | ||
2816 | res->state &= ~DLM_LOCK_RES_BLOCK_DIRTY; | ||
2817 | spin_unlock(&res->spinlock); | ||
2818 | 2811 | ||
2812 | ret = 0; | ||
2819 | /* did the target go down or die? */ | 2813 | /* did the target go down or die? */ |
2820 | spin_lock(&dlm->spinlock); | 2814 | spin_lock(&dlm->spinlock); |
2821 | if (!test_bit(target, dlm->domain_map)) { | 2815 | if (!test_bit(target, dlm->domain_map)) { |
@@ -2826,9 +2820,21 @@ again: | |||
2826 | spin_unlock(&dlm->spinlock); | 2820 | spin_unlock(&dlm->spinlock); |
2827 | 2821 | ||
2828 | /* | 2822 | /* |
2823 | * if target is down, we need to clear DLM_LOCK_RES_BLOCK_DIRTY for | ||
2824 | * another try; otherwise, we are sure the MIGRATING state is there, | ||
2825 | * drop the unneded state which blocked threads trying to DIRTY | ||
2826 | */ | ||
2827 | spin_lock(&res->spinlock); | ||
2828 | BUG_ON(!(res->state & DLM_LOCK_RES_BLOCK_DIRTY)); | ||
2829 | res->state &= ~DLM_LOCK_RES_BLOCK_DIRTY; | ||
2830 | if (!ret) | ||
2831 | BUG_ON(!(res->state & DLM_LOCK_RES_MIGRATING)); | ||
2832 | spin_unlock(&res->spinlock); | ||
2833 | |||
2834 | /* | ||
2829 | * at this point: | 2835 | * at this point: |
2830 | * | 2836 | * |
2831 | * o the DLM_LOCK_RES_MIGRATING flag is set | 2837 | * o the DLM_LOCK_RES_MIGRATING flag is set if target not down |
2832 | * o there are no pending asts on this lockres | 2838 | * o there are no pending asts on this lockres |
2833 | * o all processes trying to reserve an ast on this | 2839 | * o all processes trying to reserve an ast on this |
2834 | * lockres must wait for the MIGRATING flag to clear | 2840 | * lockres must wait for the MIGRATING flag to clear |
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index f8b75ce4be70..9dfaac73b36d 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c | |||
@@ -463,7 +463,7 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm) | |||
463 | if (dlm->reco.dead_node == O2NM_INVALID_NODE_NUM) { | 463 | if (dlm->reco.dead_node == O2NM_INVALID_NODE_NUM) { |
464 | int bit; | 464 | int bit; |
465 | 465 | ||
466 | bit = find_next_bit (dlm->recovery_map, O2NM_MAX_NODES+1, 0); | 466 | bit = find_next_bit (dlm->recovery_map, O2NM_MAX_NODES, 0); |
467 | if (bit >= O2NM_MAX_NODES || bit < 0) | 467 | if (bit >= O2NM_MAX_NODES || bit < 0) |
468 | dlm_set_reco_dead_node(dlm, O2NM_INVALID_NODE_NUM); | 468 | dlm_set_reco_dead_node(dlm, O2NM_INVALID_NODE_NUM); |
469 | else | 469 | else |
diff --git a/fs/ocfs2/dlmfs/dlmfs.c b/fs/ocfs2/dlmfs/dlmfs.c index b83d6107a1f5..bef34d0528d5 100644 --- a/fs/ocfs2/dlmfs/dlmfs.c +++ b/fs/ocfs2/dlmfs/dlmfs.c | |||
@@ -182,8 +182,7 @@ static int dlmfs_file_release(struct inode *inode, | |||
182 | { | 182 | { |
183 | int level, status; | 183 | int level, status; |
184 | struct dlmfs_inode_private *ip = DLMFS_I(inode); | 184 | struct dlmfs_inode_private *ip = DLMFS_I(inode); |
185 | struct dlmfs_filp_private *fp = | 185 | struct dlmfs_filp_private *fp = file->private_data; |
186 | (struct dlmfs_filp_private *) file->private_data; | ||
187 | 186 | ||
188 | if (S_ISDIR(inode->i_mode)) | 187 | if (S_ISDIR(inode->i_mode)) |
189 | BUG(); | 188 | BUG(); |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 39eb16ac5f98..5e02a893f46e 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -2966,7 +2966,7 @@ static const struct seq_operations ocfs2_dlm_seq_ops = { | |||
2966 | 2966 | ||
2967 | static int ocfs2_dlm_debug_release(struct inode *inode, struct file *file) | 2967 | static int ocfs2_dlm_debug_release(struct inode *inode, struct file *file) |
2968 | { | 2968 | { |
2969 | struct seq_file *seq = (struct seq_file *) file->private_data; | 2969 | struct seq_file *seq = file->private_data; |
2970 | struct ocfs2_dlm_seq_priv *priv = seq->private; | 2970 | struct ocfs2_dlm_seq_priv *priv = seq->private; |
2971 | struct ocfs2_lock_res *res = &priv->p_iter_res; | 2971 | struct ocfs2_lock_res *res = &priv->p_iter_res; |
2972 | 2972 | ||
@@ -3000,7 +3000,7 @@ static int ocfs2_dlm_debug_open(struct inode *inode, struct file *file) | |||
3000 | goto out; | 3000 | goto out; |
3001 | } | 3001 | } |
3002 | 3002 | ||
3003 | seq = (struct seq_file *) file->private_data; | 3003 | seq = file->private_data; |
3004 | seq->private = priv; | 3004 | seq->private = priv; |
3005 | 3005 | ||
3006 | ocfs2_add_lockres_tracking(&priv->p_iter_res, | 3006 | ocfs2_add_lockres_tracking(&priv->p_iter_res, |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 6a13ea64c447..2b10b36d1577 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
@@ -724,28 +724,55 @@ leave: | |||
724 | return status; | 724 | return status; |
725 | } | 725 | } |
726 | 726 | ||
727 | /* | ||
728 | * While a write will already be ordering the data, a truncate will not. | ||
729 | * Thus, we need to explicitly order the zeroed pages. | ||
730 | */ | ||
731 | static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode) | ||
732 | { | ||
733 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
734 | handle_t *handle = NULL; | ||
735 | int ret = 0; | ||
736 | |||
737 | if (!ocfs2_should_order_data(inode)) | ||
738 | goto out; | ||
739 | |||
740 | handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); | ||
741 | if (IS_ERR(handle)) { | ||
742 | ret = -ENOMEM; | ||
743 | mlog_errno(ret); | ||
744 | goto out; | ||
745 | } | ||
746 | |||
747 | ret = ocfs2_jbd2_file_inode(handle, inode); | ||
748 | if (ret < 0) | ||
749 | mlog_errno(ret); | ||
750 | |||
751 | out: | ||
752 | if (ret) { | ||
753 | if (!IS_ERR(handle)) | ||
754 | ocfs2_commit_trans(osb, handle); | ||
755 | handle = ERR_PTR(ret); | ||
756 | } | ||
757 | return handle; | ||
758 | } | ||
759 | |||
727 | /* Some parts of this taken from generic_cont_expand, which turned out | 760 | /* Some parts of this taken from generic_cont_expand, which turned out |
728 | * to be too fragile to do exactly what we need without us having to | 761 | * to be too fragile to do exactly what we need without us having to |
729 | * worry about recursive locking in ->write_begin() and ->write_end(). */ | 762 | * worry about recursive locking in ->write_begin() and ->write_end(). */ |
730 | static int ocfs2_write_zero_page(struct inode *inode, | 763 | static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, |
731 | u64 size) | 764 | u64 abs_to) |
732 | { | 765 | { |
733 | struct address_space *mapping = inode->i_mapping; | 766 | struct address_space *mapping = inode->i_mapping; |
734 | struct page *page; | 767 | struct page *page; |
735 | unsigned long index; | 768 | unsigned long index = abs_from >> PAGE_CACHE_SHIFT; |
736 | unsigned int offset; | ||
737 | handle_t *handle = NULL; | 769 | handle_t *handle = NULL; |
738 | int ret; | 770 | int ret = 0; |
771 | unsigned zero_from, zero_to, block_start, block_end; | ||
739 | 772 | ||
740 | offset = (size & (PAGE_CACHE_SIZE-1)); /* Within page */ | 773 | BUG_ON(abs_from >= abs_to); |
741 | /* ugh. in prepare/commit_write, if from==to==start of block, we | 774 | BUG_ON(abs_to > (((u64)index + 1) << PAGE_CACHE_SHIFT)); |
742 | ** skip the prepare. make sure we never send an offset for the start | 775 | BUG_ON(abs_from & (inode->i_blkbits - 1)); |
743 | ** of a block | ||
744 | */ | ||
745 | if ((offset & (inode->i_sb->s_blocksize - 1)) == 0) { | ||
746 | offset++; | ||
747 | } | ||
748 | index = size >> PAGE_CACHE_SHIFT; | ||
749 | 776 | ||
750 | page = grab_cache_page(mapping, index); | 777 | page = grab_cache_page(mapping, index); |
751 | if (!page) { | 778 | if (!page) { |
@@ -754,31 +781,56 @@ static int ocfs2_write_zero_page(struct inode *inode, | |||
754 | goto out; | 781 | goto out; |
755 | } | 782 | } |
756 | 783 | ||
757 | ret = ocfs2_prepare_write_nolock(inode, page, offset, offset); | 784 | /* Get the offsets within the page that we want to zero */ |
758 | if (ret < 0) { | 785 | zero_from = abs_from & (PAGE_CACHE_SIZE - 1); |
759 | mlog_errno(ret); | 786 | zero_to = abs_to & (PAGE_CACHE_SIZE - 1); |
760 | goto out_unlock; | 787 | if (!zero_to) |
761 | } | 788 | zero_to = PAGE_CACHE_SIZE; |
762 | 789 | ||
763 | if (ocfs2_should_order_data(inode)) { | 790 | mlog(0, |
764 | handle = ocfs2_start_walk_page_trans(inode, page, offset, | 791 | "abs_from = %llu, abs_to = %llu, index = %lu, zero_from = %u, zero_to = %u\n", |
765 | offset); | 792 | (unsigned long long)abs_from, (unsigned long long)abs_to, |
766 | if (IS_ERR(handle)) { | 793 | index, zero_from, zero_to); |
767 | ret = PTR_ERR(handle); | 794 | |
768 | handle = NULL; | 795 | /* We know that zero_from is block aligned */ |
796 | for (block_start = zero_from; block_start < zero_to; | ||
797 | block_start = block_end) { | ||
798 | block_end = block_start + (1 << inode->i_blkbits); | ||
799 | |||
800 | /* | ||
801 | * block_start is block-aligned. Bump it by one to | ||
802 | * force ocfs2_{prepare,commit}_write() to zero the | ||
803 | * whole block. | ||
804 | */ | ||
805 | ret = ocfs2_prepare_write_nolock(inode, page, | ||
806 | block_start + 1, | ||
807 | block_start + 1); | ||
808 | if (ret < 0) { | ||
809 | mlog_errno(ret); | ||
769 | goto out_unlock; | 810 | goto out_unlock; |
770 | } | 811 | } |
771 | } | ||
772 | 812 | ||
773 | /* must not update i_size! */ | 813 | if (!handle) { |
774 | ret = block_commit_write(page, offset, offset); | 814 | handle = ocfs2_zero_start_ordered_transaction(inode); |
775 | if (ret < 0) | 815 | if (IS_ERR(handle)) { |
776 | mlog_errno(ret); | 816 | ret = PTR_ERR(handle); |
777 | else | 817 | handle = NULL; |
778 | ret = 0; | 818 | break; |
819 | } | ||
820 | } | ||
821 | |||
822 | /* must not update i_size! */ | ||
823 | ret = block_commit_write(page, block_start + 1, | ||
824 | block_start + 1); | ||
825 | if (ret < 0) | ||
826 | mlog_errno(ret); | ||
827 | else | ||
828 | ret = 0; | ||
829 | } | ||
779 | 830 | ||
780 | if (handle) | 831 | if (handle) |
781 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); | 832 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); |
833 | |||
782 | out_unlock: | 834 | out_unlock: |
783 | unlock_page(page); | 835 | unlock_page(page); |
784 | page_cache_release(page); | 836 | page_cache_release(page); |
@@ -786,22 +838,114 @@ out: | |||
786 | return ret; | 838 | return ret; |
787 | } | 839 | } |
788 | 840 | ||
789 | static int ocfs2_zero_extend(struct inode *inode, | 841 | /* |
790 | u64 zero_to_size) | 842 | * Find the next range to zero. We do this in terms of bytes because |
843 | * that's what ocfs2_zero_extend() wants, and it is dealing with the | ||
844 | * pagecache. We may return multiple extents. | ||
845 | * | ||
846 | * zero_start and zero_end are ocfs2_zero_extend()s current idea of what | ||
847 | * needs to be zeroed. range_start and range_end return the next zeroing | ||
848 | * range. A subsequent call should pass the previous range_end as its | ||
849 | * zero_start. If range_end is 0, there's nothing to do. | ||
850 | * | ||
851 | * Unwritten extents are skipped over. Refcounted extents are CoWd. | ||
852 | */ | ||
853 | static int ocfs2_zero_extend_get_range(struct inode *inode, | ||
854 | struct buffer_head *di_bh, | ||
855 | u64 zero_start, u64 zero_end, | ||
856 | u64 *range_start, u64 *range_end) | ||
791 | { | 857 | { |
792 | int ret = 0; | 858 | int rc = 0, needs_cow = 0; |
793 | u64 start_off; | 859 | u32 p_cpos, zero_clusters = 0; |
794 | struct super_block *sb = inode->i_sb; | 860 | u32 zero_cpos = |
861 | zero_start >> OCFS2_SB(inode->i_sb)->s_clustersize_bits; | ||
862 | u32 last_cpos = ocfs2_clusters_for_bytes(inode->i_sb, zero_end); | ||
863 | unsigned int num_clusters = 0; | ||
864 | unsigned int ext_flags = 0; | ||
795 | 865 | ||
796 | start_off = ocfs2_align_bytes_to_blocks(sb, i_size_read(inode)); | 866 | while (zero_cpos < last_cpos) { |
797 | while (start_off < zero_to_size) { | 867 | rc = ocfs2_get_clusters(inode, zero_cpos, &p_cpos, |
798 | ret = ocfs2_write_zero_page(inode, start_off); | 868 | &num_clusters, &ext_flags); |
799 | if (ret < 0) { | 869 | if (rc) { |
800 | mlog_errno(ret); | 870 | mlog_errno(rc); |
871 | goto out; | ||
872 | } | ||
873 | |||
874 | if (p_cpos && !(ext_flags & OCFS2_EXT_UNWRITTEN)) { | ||
875 | zero_clusters = num_clusters; | ||
876 | if (ext_flags & OCFS2_EXT_REFCOUNTED) | ||
877 | needs_cow = 1; | ||
878 | break; | ||
879 | } | ||
880 | |||
881 | zero_cpos += num_clusters; | ||
882 | } | ||
883 | if (!zero_clusters) { | ||
884 | *range_end = 0; | ||
885 | goto out; | ||
886 | } | ||
887 | |||
888 | while ((zero_cpos + zero_clusters) < last_cpos) { | ||
889 | rc = ocfs2_get_clusters(inode, zero_cpos + zero_clusters, | ||
890 | &p_cpos, &num_clusters, | ||
891 | &ext_flags); | ||
892 | if (rc) { | ||
893 | mlog_errno(rc); | ||
801 | goto out; | 894 | goto out; |
802 | } | 895 | } |
803 | 896 | ||
804 | start_off += sb->s_blocksize; | 897 | if (!p_cpos || (ext_flags & OCFS2_EXT_UNWRITTEN)) |
898 | break; | ||
899 | if (ext_flags & OCFS2_EXT_REFCOUNTED) | ||
900 | needs_cow = 1; | ||
901 | zero_clusters += num_clusters; | ||
902 | } | ||
903 | if ((zero_cpos + zero_clusters) > last_cpos) | ||
904 | zero_clusters = last_cpos - zero_cpos; | ||
905 | |||
906 | if (needs_cow) { | ||
907 | rc = ocfs2_refcount_cow(inode, di_bh, zero_cpos, zero_clusters, | ||
908 | UINT_MAX); | ||
909 | if (rc) { | ||
910 | mlog_errno(rc); | ||
911 | goto out; | ||
912 | } | ||
913 | } | ||
914 | |||
915 | *range_start = ocfs2_clusters_to_bytes(inode->i_sb, zero_cpos); | ||
916 | *range_end = ocfs2_clusters_to_bytes(inode->i_sb, | ||
917 | zero_cpos + zero_clusters); | ||
918 | |||
919 | out: | ||
920 | return rc; | ||
921 | } | ||
922 | |||
923 | /* | ||
924 | * Zero one range returned from ocfs2_zero_extend_get_range(). The caller | ||
925 | * has made sure that the entire range needs zeroing. | ||
926 | */ | ||
927 | static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start, | ||
928 | u64 range_end) | ||
929 | { | ||
930 | int rc = 0; | ||
931 | u64 next_pos; | ||
932 | u64 zero_pos = range_start; | ||
933 | |||
934 | mlog(0, "range_start = %llu, range_end = %llu\n", | ||
935 | (unsigned long long)range_start, | ||
936 | (unsigned long long)range_end); | ||
937 | BUG_ON(range_start >= range_end); | ||
938 | |||
939 | while (zero_pos < range_end) { | ||
940 | next_pos = (zero_pos & PAGE_CACHE_MASK) + PAGE_CACHE_SIZE; | ||
941 | if (next_pos > range_end) | ||
942 | next_pos = range_end; | ||
943 | rc = ocfs2_write_zero_page(inode, zero_pos, next_pos); | ||
944 | if (rc < 0) { | ||
945 | mlog_errno(rc); | ||
946 | break; | ||
947 | } | ||
948 | zero_pos = next_pos; | ||
805 | 949 | ||
806 | /* | 950 | /* |
807 | * Very large extends have the potential to lock up | 951 | * Very large extends have the potential to lock up |
@@ -810,16 +954,63 @@ static int ocfs2_zero_extend(struct inode *inode, | |||
810 | cond_resched(); | 954 | cond_resched(); |
811 | } | 955 | } |
812 | 956 | ||
813 | out: | 957 | return rc; |
958 | } | ||
959 | |||
960 | int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, | ||
961 | loff_t zero_to_size) | ||
962 | { | ||
963 | int ret = 0; | ||
964 | u64 zero_start, range_start = 0, range_end = 0; | ||
965 | struct super_block *sb = inode->i_sb; | ||
966 | |||
967 | zero_start = ocfs2_align_bytes_to_blocks(sb, i_size_read(inode)); | ||
968 | mlog(0, "zero_start %llu for i_size %llu\n", | ||
969 | (unsigned long long)zero_start, | ||
970 | (unsigned long long)i_size_read(inode)); | ||
971 | while (zero_start < zero_to_size) { | ||
972 | ret = ocfs2_zero_extend_get_range(inode, di_bh, zero_start, | ||
973 | zero_to_size, | ||
974 | &range_start, | ||
975 | &range_end); | ||
976 | if (ret) { | ||
977 | mlog_errno(ret); | ||
978 | break; | ||
979 | } | ||
980 | if (!range_end) | ||
981 | break; | ||
982 | /* Trim the ends */ | ||
983 | if (range_start < zero_start) | ||
984 | range_start = zero_start; | ||
985 | if (range_end > zero_to_size) | ||
986 | range_end = zero_to_size; | ||
987 | |||
988 | ret = ocfs2_zero_extend_range(inode, range_start, | ||
989 | range_end); | ||
990 | if (ret) { | ||
991 | mlog_errno(ret); | ||
992 | break; | ||
993 | } | ||
994 | zero_start = range_end; | ||
995 | } | ||
996 | |||
814 | return ret; | 997 | return ret; |
815 | } | 998 | } |
816 | 999 | ||
817 | int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, u64 zero_to) | 1000 | int ocfs2_extend_no_holes(struct inode *inode, struct buffer_head *di_bh, |
1001 | u64 new_i_size, u64 zero_to) | ||
818 | { | 1002 | { |
819 | int ret; | 1003 | int ret; |
820 | u32 clusters_to_add; | 1004 | u32 clusters_to_add; |
821 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 1005 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
822 | 1006 | ||
1007 | /* | ||
1008 | * Only quota files call this without a bh, and they can't be | ||
1009 | * refcounted. | ||
1010 | */ | ||
1011 | BUG_ON(!di_bh && (oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL)); | ||
1012 | BUG_ON(!di_bh && !(oi->ip_flags & OCFS2_INODE_SYSTEM_FILE)); | ||
1013 | |||
823 | clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size); | 1014 | clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size); |
824 | if (clusters_to_add < oi->ip_clusters) | 1015 | if (clusters_to_add < oi->ip_clusters) |
825 | clusters_to_add = 0; | 1016 | clusters_to_add = 0; |
@@ -840,7 +1031,7 @@ int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, u64 zero_to) | |||
840 | * still need to zero the area between the old i_size and the | 1031 | * still need to zero the area between the old i_size and the |
841 | * new i_size. | 1032 | * new i_size. |
842 | */ | 1033 | */ |
843 | ret = ocfs2_zero_extend(inode, zero_to); | 1034 | ret = ocfs2_zero_extend(inode, di_bh, zero_to); |
844 | if (ret < 0) | 1035 | if (ret < 0) |
845 | mlog_errno(ret); | 1036 | mlog_errno(ret); |
846 | 1037 | ||
@@ -862,27 +1053,15 @@ static int ocfs2_extend_file(struct inode *inode, | |||
862 | goto out; | 1053 | goto out; |
863 | 1054 | ||
864 | if (i_size_read(inode) == new_i_size) | 1055 | if (i_size_read(inode) == new_i_size) |
865 | goto out; | 1056 | goto out; |
866 | BUG_ON(new_i_size < i_size_read(inode)); | 1057 | BUG_ON(new_i_size < i_size_read(inode)); |
867 | 1058 | ||
868 | /* | 1059 | /* |
869 | * Fall through for converting inline data, even if the fs | ||
870 | * supports sparse files. | ||
871 | * | ||
872 | * The check for inline data here is legal - nobody can add | ||
873 | * the feature since we have i_mutex. We must check it again | ||
874 | * after acquiring ip_alloc_sem though, as paths like mmap | ||
875 | * might have raced us to converting the inode to extents. | ||
876 | */ | ||
877 | if (!(oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) | ||
878 | && ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) | ||
879 | goto out_update_size; | ||
880 | |||
881 | /* | ||
882 | * The alloc sem blocks people in read/write from reading our | 1060 | * The alloc sem blocks people in read/write from reading our |
883 | * allocation until we're done changing it. We depend on | 1061 | * allocation until we're done changing it. We depend on |
884 | * i_mutex to block other extend/truncate calls while we're | 1062 | * i_mutex to block other extend/truncate calls while we're |
885 | * here. | 1063 | * here. We even have to hold it for sparse files because there |
1064 | * might be some tail zeroing. | ||
886 | */ | 1065 | */ |
887 | down_write(&oi->ip_alloc_sem); | 1066 | down_write(&oi->ip_alloc_sem); |
888 | 1067 | ||
@@ -899,14 +1078,16 @@ static int ocfs2_extend_file(struct inode *inode, | |||
899 | ret = ocfs2_convert_inline_data_to_extents(inode, di_bh); | 1078 | ret = ocfs2_convert_inline_data_to_extents(inode, di_bh); |
900 | if (ret) { | 1079 | if (ret) { |
901 | up_write(&oi->ip_alloc_sem); | 1080 | up_write(&oi->ip_alloc_sem); |
902 | |||
903 | mlog_errno(ret); | 1081 | mlog_errno(ret); |
904 | goto out; | 1082 | goto out; |
905 | } | 1083 | } |
906 | } | 1084 | } |
907 | 1085 | ||
908 | if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) | 1086 | if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) |
909 | ret = ocfs2_extend_no_holes(inode, new_i_size, new_i_size); | 1087 | ret = ocfs2_zero_extend(inode, di_bh, new_i_size); |
1088 | else | ||
1089 | ret = ocfs2_extend_no_holes(inode, di_bh, new_i_size, | ||
1090 | new_i_size); | ||
910 | 1091 | ||
911 | up_write(&oi->ip_alloc_sem); | 1092 | up_write(&oi->ip_alloc_sem); |
912 | 1093 | ||
diff --git a/fs/ocfs2/file.h b/fs/ocfs2/file.h index d66cf4f7c70e..97bf761c9e7c 100644 --- a/fs/ocfs2/file.h +++ b/fs/ocfs2/file.h | |||
@@ -54,8 +54,10 @@ int ocfs2_add_inode_data(struct ocfs2_super *osb, | |||
54 | int ocfs2_simple_size_update(struct inode *inode, | 54 | int ocfs2_simple_size_update(struct inode *inode, |
55 | struct buffer_head *di_bh, | 55 | struct buffer_head *di_bh, |
56 | u64 new_i_size); | 56 | u64 new_i_size); |
57 | int ocfs2_extend_no_holes(struct inode *inode, u64 new_i_size, | 57 | int ocfs2_extend_no_holes(struct inode *inode, struct buffer_head *di_bh, |
58 | u64 zero_to); | 58 | u64 new_i_size, u64 zero_to); |
59 | int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, | ||
60 | loff_t zero_to); | ||
59 | int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); | 61 | int ocfs2_setattr(struct dentry *dentry, struct iattr *attr); |
60 | int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, | 62 | int ocfs2_getattr(struct vfsmount *mnt, struct dentry *dentry, |
61 | struct kstat *stat); | 63 | struct kstat *stat); |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index 47878cf16418..9b57c0350ff9 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
@@ -472,7 +472,7 @@ static inline struct ocfs2_triggers *to_ocfs2_trigger(struct jbd2_buffer_trigger | |||
472 | return container_of(triggers, struct ocfs2_triggers, ot_triggers); | 472 | return container_of(triggers, struct ocfs2_triggers, ot_triggers); |
473 | } | 473 | } |
474 | 474 | ||
475 | static void ocfs2_commit_trigger(struct jbd2_buffer_trigger_type *triggers, | 475 | static void ocfs2_frozen_trigger(struct jbd2_buffer_trigger_type *triggers, |
476 | struct buffer_head *bh, | 476 | struct buffer_head *bh, |
477 | void *data, size_t size) | 477 | void *data, size_t size) |
478 | { | 478 | { |
@@ -491,7 +491,7 @@ static void ocfs2_commit_trigger(struct jbd2_buffer_trigger_type *triggers, | |||
491 | * Quota blocks have their own trigger because the struct ocfs2_block_check | 491 | * Quota blocks have their own trigger because the struct ocfs2_block_check |
492 | * offset depends on the blocksize. | 492 | * offset depends on the blocksize. |
493 | */ | 493 | */ |
494 | static void ocfs2_dq_commit_trigger(struct jbd2_buffer_trigger_type *triggers, | 494 | static void ocfs2_dq_frozen_trigger(struct jbd2_buffer_trigger_type *triggers, |
495 | struct buffer_head *bh, | 495 | struct buffer_head *bh, |
496 | void *data, size_t size) | 496 | void *data, size_t size) |
497 | { | 497 | { |
@@ -511,7 +511,7 @@ static void ocfs2_dq_commit_trigger(struct jbd2_buffer_trigger_type *triggers, | |||
511 | * Directory blocks also have their own trigger because the | 511 | * Directory blocks also have their own trigger because the |
512 | * struct ocfs2_block_check offset depends on the blocksize. | 512 | * struct ocfs2_block_check offset depends on the blocksize. |
513 | */ | 513 | */ |
514 | static void ocfs2_db_commit_trigger(struct jbd2_buffer_trigger_type *triggers, | 514 | static void ocfs2_db_frozen_trigger(struct jbd2_buffer_trigger_type *triggers, |
515 | struct buffer_head *bh, | 515 | struct buffer_head *bh, |
516 | void *data, size_t size) | 516 | void *data, size_t size) |
517 | { | 517 | { |
@@ -544,7 +544,7 @@ static void ocfs2_abort_trigger(struct jbd2_buffer_trigger_type *triggers, | |||
544 | 544 | ||
545 | static struct ocfs2_triggers di_triggers = { | 545 | static struct ocfs2_triggers di_triggers = { |
546 | .ot_triggers = { | 546 | .ot_triggers = { |
547 | .t_commit = ocfs2_commit_trigger, | 547 | .t_frozen = ocfs2_frozen_trigger, |
548 | .t_abort = ocfs2_abort_trigger, | 548 | .t_abort = ocfs2_abort_trigger, |
549 | }, | 549 | }, |
550 | .ot_offset = offsetof(struct ocfs2_dinode, i_check), | 550 | .ot_offset = offsetof(struct ocfs2_dinode, i_check), |
@@ -552,7 +552,7 @@ static struct ocfs2_triggers di_triggers = { | |||
552 | 552 | ||
553 | static struct ocfs2_triggers eb_triggers = { | 553 | static struct ocfs2_triggers eb_triggers = { |
554 | .ot_triggers = { | 554 | .ot_triggers = { |
555 | .t_commit = ocfs2_commit_trigger, | 555 | .t_frozen = ocfs2_frozen_trigger, |
556 | .t_abort = ocfs2_abort_trigger, | 556 | .t_abort = ocfs2_abort_trigger, |
557 | }, | 557 | }, |
558 | .ot_offset = offsetof(struct ocfs2_extent_block, h_check), | 558 | .ot_offset = offsetof(struct ocfs2_extent_block, h_check), |
@@ -560,7 +560,7 @@ static struct ocfs2_triggers eb_triggers = { | |||
560 | 560 | ||
561 | static struct ocfs2_triggers rb_triggers = { | 561 | static struct ocfs2_triggers rb_triggers = { |
562 | .ot_triggers = { | 562 | .ot_triggers = { |
563 | .t_commit = ocfs2_commit_trigger, | 563 | .t_frozen = ocfs2_frozen_trigger, |
564 | .t_abort = ocfs2_abort_trigger, | 564 | .t_abort = ocfs2_abort_trigger, |
565 | }, | 565 | }, |
566 | .ot_offset = offsetof(struct ocfs2_refcount_block, rf_check), | 566 | .ot_offset = offsetof(struct ocfs2_refcount_block, rf_check), |
@@ -568,7 +568,7 @@ static struct ocfs2_triggers rb_triggers = { | |||
568 | 568 | ||
569 | static struct ocfs2_triggers gd_triggers = { | 569 | static struct ocfs2_triggers gd_triggers = { |
570 | .ot_triggers = { | 570 | .ot_triggers = { |
571 | .t_commit = ocfs2_commit_trigger, | 571 | .t_frozen = ocfs2_frozen_trigger, |
572 | .t_abort = ocfs2_abort_trigger, | 572 | .t_abort = ocfs2_abort_trigger, |
573 | }, | 573 | }, |
574 | .ot_offset = offsetof(struct ocfs2_group_desc, bg_check), | 574 | .ot_offset = offsetof(struct ocfs2_group_desc, bg_check), |
@@ -576,14 +576,14 @@ static struct ocfs2_triggers gd_triggers = { | |||
576 | 576 | ||
577 | static struct ocfs2_triggers db_triggers = { | 577 | static struct ocfs2_triggers db_triggers = { |
578 | .ot_triggers = { | 578 | .ot_triggers = { |
579 | .t_commit = ocfs2_db_commit_trigger, | 579 | .t_frozen = ocfs2_db_frozen_trigger, |
580 | .t_abort = ocfs2_abort_trigger, | 580 | .t_abort = ocfs2_abort_trigger, |
581 | }, | 581 | }, |
582 | }; | 582 | }; |
583 | 583 | ||
584 | static struct ocfs2_triggers xb_triggers = { | 584 | static struct ocfs2_triggers xb_triggers = { |
585 | .ot_triggers = { | 585 | .ot_triggers = { |
586 | .t_commit = ocfs2_commit_trigger, | 586 | .t_frozen = ocfs2_frozen_trigger, |
587 | .t_abort = ocfs2_abort_trigger, | 587 | .t_abort = ocfs2_abort_trigger, |
588 | }, | 588 | }, |
589 | .ot_offset = offsetof(struct ocfs2_xattr_block, xb_check), | 589 | .ot_offset = offsetof(struct ocfs2_xattr_block, xb_check), |
@@ -591,14 +591,14 @@ static struct ocfs2_triggers xb_triggers = { | |||
591 | 591 | ||
592 | static struct ocfs2_triggers dq_triggers = { | 592 | static struct ocfs2_triggers dq_triggers = { |
593 | .ot_triggers = { | 593 | .ot_triggers = { |
594 | .t_commit = ocfs2_dq_commit_trigger, | 594 | .t_frozen = ocfs2_dq_frozen_trigger, |
595 | .t_abort = ocfs2_abort_trigger, | 595 | .t_abort = ocfs2_abort_trigger, |
596 | }, | 596 | }, |
597 | }; | 597 | }; |
598 | 598 | ||
599 | static struct ocfs2_triggers dr_triggers = { | 599 | static struct ocfs2_triggers dr_triggers = { |
600 | .ot_triggers = { | 600 | .ot_triggers = { |
601 | .t_commit = ocfs2_commit_trigger, | 601 | .t_frozen = ocfs2_frozen_trigger, |
602 | .t_abort = ocfs2_abort_trigger, | 602 | .t_abort = ocfs2_abort_trigger, |
603 | }, | 603 | }, |
604 | .ot_offset = offsetof(struct ocfs2_dx_root_block, dr_check), | 604 | .ot_offset = offsetof(struct ocfs2_dx_root_block, dr_check), |
@@ -606,7 +606,7 @@ static struct ocfs2_triggers dr_triggers = { | |||
606 | 606 | ||
607 | static struct ocfs2_triggers dl_triggers = { | 607 | static struct ocfs2_triggers dl_triggers = { |
608 | .ot_triggers = { | 608 | .ot_triggers = { |
609 | .t_commit = ocfs2_commit_trigger, | 609 | .t_frozen = ocfs2_frozen_trigger, |
610 | .t_abort = ocfs2_abort_trigger, | 610 | .t_abort = ocfs2_abort_trigger, |
611 | }, | 611 | }, |
612 | .ot_offset = offsetof(struct ocfs2_dx_leaf, dl_check), | 612 | .ot_offset = offsetof(struct ocfs2_dx_leaf, dl_check), |
@@ -760,13 +760,13 @@ void ocfs2_set_journal_params(struct ocfs2_super *osb) | |||
760 | if (osb->osb_commit_interval) | 760 | if (osb->osb_commit_interval) |
761 | commit_interval = osb->osb_commit_interval; | 761 | commit_interval = osb->osb_commit_interval; |
762 | 762 | ||
763 | spin_lock(&journal->j_state_lock); | 763 | write_lock(&journal->j_state_lock); |
764 | journal->j_commit_interval = commit_interval; | 764 | journal->j_commit_interval = commit_interval; |
765 | if (osb->s_mount_opt & OCFS2_MOUNT_BARRIER) | 765 | if (osb->s_mount_opt & OCFS2_MOUNT_BARRIER) |
766 | journal->j_flags |= JBD2_BARRIER; | 766 | journal->j_flags |= JBD2_BARRIER; |
767 | else | 767 | else |
768 | journal->j_flags &= ~JBD2_BARRIER; | 768 | journal->j_flags &= ~JBD2_BARRIER; |
769 | spin_unlock(&journal->j_state_lock); | 769 | write_unlock(&journal->j_state_lock); |
770 | } | 770 | } |
771 | 771 | ||
772 | int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty) | 772 | int ocfs2_journal_init(struct ocfs2_journal *journal, int *dirty) |
@@ -1936,7 +1936,7 @@ void ocfs2_orphan_scan_work(struct work_struct *work) | |||
1936 | mutex_lock(&os->os_lock); | 1936 | mutex_lock(&os->os_lock); |
1937 | ocfs2_queue_orphan_scan(osb); | 1937 | ocfs2_queue_orphan_scan(osb); |
1938 | if (atomic_read(&os->os_state) == ORPHAN_SCAN_ACTIVE) | 1938 | if (atomic_read(&os->os_state) == ORPHAN_SCAN_ACTIVE) |
1939 | schedule_delayed_work(&os->os_orphan_scan_work, | 1939 | queue_delayed_work(ocfs2_wq, &os->os_orphan_scan_work, |
1940 | ocfs2_orphan_scan_timeout()); | 1940 | ocfs2_orphan_scan_timeout()); |
1941 | mutex_unlock(&os->os_lock); | 1941 | mutex_unlock(&os->os_lock); |
1942 | } | 1942 | } |
@@ -1976,8 +1976,8 @@ void ocfs2_orphan_scan_start(struct ocfs2_super *osb) | |||
1976 | atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE); | 1976 | atomic_set(&os->os_state, ORPHAN_SCAN_INACTIVE); |
1977 | else { | 1977 | else { |
1978 | atomic_set(&os->os_state, ORPHAN_SCAN_ACTIVE); | 1978 | atomic_set(&os->os_state, ORPHAN_SCAN_ACTIVE); |
1979 | schedule_delayed_work(&os->os_orphan_scan_work, | 1979 | queue_delayed_work(ocfs2_wq, &os->os_orphan_scan_work, |
1980 | ocfs2_orphan_scan_timeout()); | 1980 | ocfs2_orphan_scan_timeout()); |
1981 | } | 1981 | } |
1982 | } | 1982 | } |
1983 | 1983 | ||
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index 3d7419682dc0..ec6adbf8f551 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c | |||
@@ -118,6 +118,7 @@ unsigned int ocfs2_la_default_mb(struct ocfs2_super *osb) | |||
118 | { | 118 | { |
119 | unsigned int la_mb; | 119 | unsigned int la_mb; |
120 | unsigned int gd_mb; | 120 | unsigned int gd_mb; |
121 | unsigned int la_max_mb; | ||
121 | unsigned int megs_per_slot; | 122 | unsigned int megs_per_slot; |
122 | struct super_block *sb = osb->sb; | 123 | struct super_block *sb = osb->sb; |
123 | 124 | ||
@@ -182,6 +183,12 @@ unsigned int ocfs2_la_default_mb(struct ocfs2_super *osb) | |||
182 | if (megs_per_slot < la_mb) | 183 | if (megs_per_slot < la_mb) |
183 | la_mb = megs_per_slot; | 184 | la_mb = megs_per_slot; |
184 | 185 | ||
186 | /* We can't store more bits than we can in a block. */ | ||
187 | la_max_mb = ocfs2_clusters_to_megabytes(osb->sb, | ||
188 | ocfs2_local_alloc_size(sb) * 8); | ||
189 | if (la_mb > la_max_mb) | ||
190 | la_mb = la_max_mb; | ||
191 | |||
185 | return la_mb; | 192 | return la_mb; |
186 | } | 193 | } |
187 | 194 | ||
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index 2bb35fe00511..4607923eb24c 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c | |||
@@ -775,7 +775,7 @@ static int ocfs2_acquire_dquot(struct dquot *dquot) | |||
775 | * locking allocators ranks above a transaction start | 775 | * locking allocators ranks above a transaction start |
776 | */ | 776 | */ |
777 | WARN_ON(journal_current_handle()); | 777 | WARN_ON(journal_current_handle()); |
778 | status = ocfs2_extend_no_holes(gqinode, | 778 | status = ocfs2_extend_no_holes(gqinode, NULL, |
779 | gqinode->i_size + (need_alloc << sb->s_blocksize_bits), | 779 | gqinode->i_size + (need_alloc << sb->s_blocksize_bits), |
780 | gqinode->i_size); | 780 | gqinode->i_size); |
781 | if (status < 0) | 781 | if (status < 0) |
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c index 8bd70d4d184d..dc78764ccc4c 100644 --- a/fs/ocfs2/quota_local.c +++ b/fs/ocfs2/quota_local.c | |||
@@ -971,7 +971,7 @@ static struct ocfs2_quota_chunk *ocfs2_local_quota_add_chunk( | |||
971 | u64 p_blkno; | 971 | u64 p_blkno; |
972 | 972 | ||
973 | /* We are protected by dqio_sem so no locking needed */ | 973 | /* We are protected by dqio_sem so no locking needed */ |
974 | status = ocfs2_extend_no_holes(lqinode, | 974 | status = ocfs2_extend_no_holes(lqinode, NULL, |
975 | lqinode->i_size + 2 * sb->s_blocksize, | 975 | lqinode->i_size + 2 * sb->s_blocksize, |
976 | lqinode->i_size); | 976 | lqinode->i_size); |
977 | if (status < 0) { | 977 | if (status < 0) { |
@@ -1114,7 +1114,7 @@ static struct ocfs2_quota_chunk *ocfs2_extend_local_quota_file( | |||
1114 | return ocfs2_local_quota_add_chunk(sb, type, offset); | 1114 | return ocfs2_local_quota_add_chunk(sb, type, offset); |
1115 | 1115 | ||
1116 | /* We are protected by dqio_sem so no locking needed */ | 1116 | /* We are protected by dqio_sem so no locking needed */ |
1117 | status = ocfs2_extend_no_holes(lqinode, | 1117 | status = ocfs2_extend_no_holes(lqinode, NULL, |
1118 | lqinode->i_size + sb->s_blocksize, | 1118 | lqinode->i_size + sb->s_blocksize, |
1119 | lqinode->i_size); | 1119 | lqinode->i_size); |
1120 | if (status < 0) { | 1120 | if (status < 0) { |
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 4793f36f6518..3ac5aa733e9c 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
@@ -2931,6 +2931,12 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle, | |||
2931 | 2931 | ||
2932 | offset = ((loff_t)cpos) << OCFS2_SB(sb)->s_clustersize_bits; | 2932 | offset = ((loff_t)cpos) << OCFS2_SB(sb)->s_clustersize_bits; |
2933 | end = offset + (new_len << OCFS2_SB(sb)->s_clustersize_bits); | 2933 | end = offset + (new_len << OCFS2_SB(sb)->s_clustersize_bits); |
2934 | /* | ||
2935 | * We only duplicate pages until we reach the page contains i_size - 1. | ||
2936 | * So trim 'end' to i_size. | ||
2937 | */ | ||
2938 | if (end > i_size_read(context->inode)) | ||
2939 | end = i_size_read(context->inode); | ||
2934 | 2940 | ||
2935 | while (offset < end) { | 2941 | while (offset < end) { |
2936 | page_index = offset >> PAGE_CACHE_SHIFT; | 2942 | page_index = offset >> PAGE_CACHE_SHIFT; |
@@ -4166,6 +4172,12 @@ static int __ocfs2_reflink(struct dentry *old_dentry, | |||
4166 | struct inode *inode = old_dentry->d_inode; | 4172 | struct inode *inode = old_dentry->d_inode; |
4167 | struct buffer_head *new_bh = NULL; | 4173 | struct buffer_head *new_bh = NULL; |
4168 | 4174 | ||
4175 | if (OCFS2_I(inode)->ip_flags & OCFS2_INODE_SYSTEM_FILE) { | ||
4176 | ret = -EINVAL; | ||
4177 | mlog_errno(ret); | ||
4178 | goto out; | ||
4179 | } | ||
4180 | |||
4169 | ret = filemap_fdatawrite(inode->i_mapping); | 4181 | ret = filemap_fdatawrite(inode->i_mapping); |
4170 | if (ret) { | 4182 | if (ret) { |
4171 | mlog_errno(ret); | 4183 | mlog_errno(ret); |
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index f4c2a9eb8c4d..a8e6a95a353f 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c | |||
@@ -741,7 +741,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb, | |||
741 | le16_to_cpu(bg->bg_free_bits_count)); | 741 | le16_to_cpu(bg->bg_free_bits_count)); |
742 | le32_add_cpu(&cl->cl_recs[alloc_rec].c_total, | 742 | le32_add_cpu(&cl->cl_recs[alloc_rec].c_total, |
743 | le16_to_cpu(bg->bg_bits)); | 743 | le16_to_cpu(bg->bg_bits)); |
744 | cl->cl_recs[alloc_rec].c_blkno = cpu_to_le64(bg->bg_blkno); | 744 | cl->cl_recs[alloc_rec].c_blkno = bg->bg_blkno; |
745 | if (le16_to_cpu(cl->cl_next_free_rec) < le16_to_cpu(cl->cl_count)) | 745 | if (le16_to_cpu(cl->cl_next_free_rec) < le16_to_cpu(cl->cl_count)) |
746 | le16_add_cpu(&cl->cl_next_free_rec, 1); | 746 | le16_add_cpu(&cl->cl_next_free_rec, 1); |
747 | 747 | ||
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 0eaa929a4dbf..03a799fdd740 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -2472,7 +2472,7 @@ static void ocfs2_delete_osb(struct ocfs2_super *osb) | |||
2472 | kfree(osb->slot_recovery_generations); | 2472 | kfree(osb->slot_recovery_generations); |
2473 | /* FIXME | 2473 | /* FIXME |
2474 | * This belongs in journal shutdown, but because we have to | 2474 | * This belongs in journal shutdown, but because we have to |
2475 | * allocate osb->journal at the start of ocfs2_initalize_osb(), | 2475 | * allocate osb->journal at the start of ocfs2_initialize_osb(), |
2476 | * we free it here. | 2476 | * we free it here. |
2477 | */ | 2477 | */ |
2478 | kfree(osb->journal); | 2478 | kfree(osb->journal); |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index e97b34842cfe..d03469f61801 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -709,7 +709,7 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode, | |||
709 | struct ocfs2_xattr_value_buf *vb, | 709 | struct ocfs2_xattr_value_buf *vb, |
710 | struct ocfs2_xattr_set_ctxt *ctxt) | 710 | struct ocfs2_xattr_set_ctxt *ctxt) |
711 | { | 711 | { |
712 | int status = 0; | 712 | int status = 0, credits; |
713 | handle_t *handle = ctxt->handle; | 713 | handle_t *handle = ctxt->handle; |
714 | enum ocfs2_alloc_restarted why; | 714 | enum ocfs2_alloc_restarted why; |
715 | u32 prev_clusters, logical_start = le32_to_cpu(vb->vb_xv->xr_clusters); | 715 | u32 prev_clusters, logical_start = le32_to_cpu(vb->vb_xv->xr_clusters); |
@@ -719,38 +719,54 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode, | |||
719 | 719 | ||
720 | ocfs2_init_xattr_value_extent_tree(&et, INODE_CACHE(inode), vb); | 720 | ocfs2_init_xattr_value_extent_tree(&et, INODE_CACHE(inode), vb); |
721 | 721 | ||
722 | status = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh, | 722 | while (clusters_to_add) { |
723 | OCFS2_JOURNAL_ACCESS_WRITE); | 723 | status = vb->vb_access(handle, INODE_CACHE(inode), vb->vb_bh, |
724 | if (status < 0) { | 724 | OCFS2_JOURNAL_ACCESS_WRITE); |
725 | mlog_errno(status); | 725 | if (status < 0) { |
726 | goto leave; | 726 | mlog_errno(status); |
727 | } | 727 | break; |
728 | } | ||
728 | 729 | ||
729 | prev_clusters = le32_to_cpu(vb->vb_xv->xr_clusters); | 730 | prev_clusters = le32_to_cpu(vb->vb_xv->xr_clusters); |
730 | status = ocfs2_add_clusters_in_btree(handle, | 731 | status = ocfs2_add_clusters_in_btree(handle, |
731 | &et, | 732 | &et, |
732 | &logical_start, | 733 | &logical_start, |
733 | clusters_to_add, | 734 | clusters_to_add, |
734 | 0, | 735 | 0, |
735 | ctxt->data_ac, | 736 | ctxt->data_ac, |
736 | ctxt->meta_ac, | 737 | ctxt->meta_ac, |
737 | &why); | 738 | &why); |
738 | if (status < 0) { | 739 | if ((status < 0) && (status != -EAGAIN)) { |
739 | mlog_errno(status); | 740 | if (status != -ENOSPC) |
740 | goto leave; | 741 | mlog_errno(status); |
741 | } | 742 | break; |
743 | } | ||
742 | 744 | ||
743 | ocfs2_journal_dirty(handle, vb->vb_bh); | 745 | ocfs2_journal_dirty(handle, vb->vb_bh); |
744 | 746 | ||
745 | clusters_to_add -= le32_to_cpu(vb->vb_xv->xr_clusters) - prev_clusters; | 747 | clusters_to_add -= le32_to_cpu(vb->vb_xv->xr_clusters) - |
748 | prev_clusters; | ||
746 | 749 | ||
747 | /* | 750 | if (why != RESTART_NONE && clusters_to_add) { |
748 | * We should have already allocated enough space before the transaction, | 751 | /* |
749 | * so no need to restart. | 752 | * We can only fail in case the alloc file doesn't give |
750 | */ | 753 | * up enough clusters. |
751 | BUG_ON(why != RESTART_NONE || clusters_to_add); | 754 | */ |
752 | 755 | BUG_ON(why == RESTART_META); | |
753 | leave: | 756 | |
757 | mlog(0, "restarting xattr value extension for %u" | ||
758 | " clusters,.\n", clusters_to_add); | ||
759 | credits = ocfs2_calc_extend_credits(inode->i_sb, | ||
760 | &vb->vb_xv->xr_list, | ||
761 | clusters_to_add); | ||
762 | status = ocfs2_extend_trans(handle, credits); | ||
763 | if (status < 0) { | ||
764 | status = -ENOMEM; | ||
765 | mlog_errno(status); | ||
766 | break; | ||
767 | } | ||
768 | } | ||
769 | } | ||
754 | 770 | ||
755 | return status; | 771 | return status; |
756 | } | 772 | } |
@@ -6788,16 +6804,15 @@ out: | |||
6788 | return ret; | 6804 | return ret; |
6789 | } | 6805 | } |
6790 | 6806 | ||
6791 | static int ocfs2_reflink_xattr_buckets(handle_t *handle, | 6807 | static int ocfs2_reflink_xattr_bucket(handle_t *handle, |
6792 | u64 blkno, u64 new_blkno, u32 clusters, | 6808 | u64 blkno, u64 new_blkno, u32 clusters, |
6809 | u32 *cpos, int num_buckets, | ||
6793 | struct ocfs2_alloc_context *meta_ac, | 6810 | struct ocfs2_alloc_context *meta_ac, |
6794 | struct ocfs2_alloc_context *data_ac, | 6811 | struct ocfs2_alloc_context *data_ac, |
6795 | struct ocfs2_reflink_xattr_tree_args *args) | 6812 | struct ocfs2_reflink_xattr_tree_args *args) |
6796 | { | 6813 | { |
6797 | int i, j, ret = 0; | 6814 | int i, j, ret = 0; |
6798 | struct super_block *sb = args->reflink->old_inode->i_sb; | 6815 | struct super_block *sb = args->reflink->old_inode->i_sb; |
6799 | u32 bpc = ocfs2_xattr_buckets_per_cluster(OCFS2_SB(sb)); | ||
6800 | u32 num_buckets = clusters * bpc; | ||
6801 | int bpb = args->old_bucket->bu_blocks; | 6816 | int bpb = args->old_bucket->bu_blocks; |
6802 | struct ocfs2_xattr_value_buf vb = { | 6817 | struct ocfs2_xattr_value_buf vb = { |
6803 | .vb_access = ocfs2_journal_access, | 6818 | .vb_access = ocfs2_journal_access, |
@@ -6816,14 +6831,6 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, | |||
6816 | break; | 6831 | break; |
6817 | } | 6832 | } |
6818 | 6833 | ||
6819 | /* | ||
6820 | * The real bucket num in this series of blocks is stored | ||
6821 | * in the 1st bucket. | ||
6822 | */ | ||
6823 | if (i == 0) | ||
6824 | num_buckets = le16_to_cpu( | ||
6825 | bucket_xh(args->old_bucket)->xh_num_buckets); | ||
6826 | |||
6827 | ret = ocfs2_xattr_bucket_journal_access(handle, | 6834 | ret = ocfs2_xattr_bucket_journal_access(handle, |
6828 | args->new_bucket, | 6835 | args->new_bucket, |
6829 | OCFS2_JOURNAL_ACCESS_CREATE); | 6836 | OCFS2_JOURNAL_ACCESS_CREATE); |
@@ -6837,6 +6844,18 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, | |||
6837 | bucket_block(args->old_bucket, j), | 6844 | bucket_block(args->old_bucket, j), |
6838 | sb->s_blocksize); | 6845 | sb->s_blocksize); |
6839 | 6846 | ||
6847 | /* | ||
6848 | * Record the start cpos so that we can use it to initialize | ||
6849 | * our xattr tree we also set the xh_num_bucket for the new | ||
6850 | * bucket. | ||
6851 | */ | ||
6852 | if (i == 0) { | ||
6853 | *cpos = le32_to_cpu(bucket_xh(args->new_bucket)-> | ||
6854 | xh_entries[0].xe_name_hash); | ||
6855 | bucket_xh(args->new_bucket)->xh_num_buckets = | ||
6856 | cpu_to_le16(num_buckets); | ||
6857 | } | ||
6858 | |||
6840 | ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket); | 6859 | ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket); |
6841 | 6860 | ||
6842 | ret = ocfs2_reflink_xattr_header(handle, args->reflink, | 6861 | ret = ocfs2_reflink_xattr_header(handle, args->reflink, |
@@ -6866,6 +6885,7 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, | |||
6866 | } | 6885 | } |
6867 | 6886 | ||
6868 | ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket); | 6887 | ocfs2_xattr_bucket_journal_dirty(handle, args->new_bucket); |
6888 | |||
6869 | ocfs2_xattr_bucket_relse(args->old_bucket); | 6889 | ocfs2_xattr_bucket_relse(args->old_bucket); |
6870 | ocfs2_xattr_bucket_relse(args->new_bucket); | 6890 | ocfs2_xattr_bucket_relse(args->new_bucket); |
6871 | } | 6891 | } |
@@ -6874,6 +6894,75 @@ static int ocfs2_reflink_xattr_buckets(handle_t *handle, | |||
6874 | ocfs2_xattr_bucket_relse(args->new_bucket); | 6894 | ocfs2_xattr_bucket_relse(args->new_bucket); |
6875 | return ret; | 6895 | return ret; |
6876 | } | 6896 | } |
6897 | |||
6898 | static int ocfs2_reflink_xattr_buckets(handle_t *handle, | ||
6899 | struct inode *inode, | ||
6900 | struct ocfs2_reflink_xattr_tree_args *args, | ||
6901 | struct ocfs2_extent_tree *et, | ||
6902 | struct ocfs2_alloc_context *meta_ac, | ||
6903 | struct ocfs2_alloc_context *data_ac, | ||
6904 | u64 blkno, u32 cpos, u32 len) | ||
6905 | { | ||
6906 | int ret, first_inserted = 0; | ||
6907 | u32 p_cluster, num_clusters, reflink_cpos = 0; | ||
6908 | u64 new_blkno; | ||
6909 | unsigned int num_buckets, reflink_buckets; | ||
6910 | unsigned int bpc = | ||
6911 | ocfs2_xattr_buckets_per_cluster(OCFS2_SB(inode->i_sb)); | ||
6912 | |||
6913 | ret = ocfs2_read_xattr_bucket(args->old_bucket, blkno); | ||
6914 | if (ret) { | ||
6915 | mlog_errno(ret); | ||
6916 | goto out; | ||
6917 | } | ||
6918 | num_buckets = le16_to_cpu(bucket_xh(args->old_bucket)->xh_num_buckets); | ||
6919 | ocfs2_xattr_bucket_relse(args->old_bucket); | ||
6920 | |||
6921 | while (len && num_buckets) { | ||
6922 | ret = ocfs2_claim_clusters(handle, data_ac, | ||
6923 | 1, &p_cluster, &num_clusters); | ||
6924 | if (ret) { | ||
6925 | mlog_errno(ret); | ||
6926 | goto out; | ||
6927 | } | ||
6928 | |||
6929 | new_blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster); | ||
6930 | reflink_buckets = min(num_buckets, bpc * num_clusters); | ||
6931 | |||
6932 | ret = ocfs2_reflink_xattr_bucket(handle, blkno, | ||
6933 | new_blkno, num_clusters, | ||
6934 | &reflink_cpos, reflink_buckets, | ||
6935 | meta_ac, data_ac, args); | ||
6936 | if (ret) { | ||
6937 | mlog_errno(ret); | ||
6938 | goto out; | ||
6939 | } | ||
6940 | |||
6941 | /* | ||
6942 | * For the 1st allocated cluster, we make it use the same cpos | ||
6943 | * so that the xattr tree looks the same as the original one | ||
6944 | * in the most case. | ||
6945 | */ | ||
6946 | if (!first_inserted) { | ||
6947 | reflink_cpos = cpos; | ||
6948 | first_inserted = 1; | ||
6949 | } | ||
6950 | ret = ocfs2_insert_extent(handle, et, reflink_cpos, new_blkno, | ||
6951 | num_clusters, 0, meta_ac); | ||
6952 | if (ret) | ||
6953 | mlog_errno(ret); | ||
6954 | |||
6955 | mlog(0, "insert new xattr extent rec start %llu len %u to %u\n", | ||
6956 | (unsigned long long)new_blkno, num_clusters, reflink_cpos); | ||
6957 | |||
6958 | len -= num_clusters; | ||
6959 | blkno += ocfs2_clusters_to_blocks(inode->i_sb, num_clusters); | ||
6960 | num_buckets -= reflink_buckets; | ||
6961 | } | ||
6962 | out: | ||
6963 | return ret; | ||
6964 | } | ||
6965 | |||
6877 | /* | 6966 | /* |
6878 | * Create the same xattr extent record in the new inode's xattr tree. | 6967 | * Create the same xattr extent record in the new inode's xattr tree. |
6879 | */ | 6968 | */ |
@@ -6885,8 +6974,6 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode, | |||
6885 | void *para) | 6974 | void *para) |
6886 | { | 6975 | { |
6887 | int ret, credits = 0; | 6976 | int ret, credits = 0; |
6888 | u32 p_cluster, num_clusters; | ||
6889 | u64 new_blkno; | ||
6890 | handle_t *handle; | 6977 | handle_t *handle; |
6891 | struct ocfs2_reflink_xattr_tree_args *args = | 6978 | struct ocfs2_reflink_xattr_tree_args *args = |
6892 | (struct ocfs2_reflink_xattr_tree_args *)para; | 6979 | (struct ocfs2_reflink_xattr_tree_args *)para; |
@@ -6895,6 +6982,9 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode, | |||
6895 | struct ocfs2_alloc_context *data_ac = NULL; | 6982 | struct ocfs2_alloc_context *data_ac = NULL; |
6896 | struct ocfs2_extent_tree et; | 6983 | struct ocfs2_extent_tree et; |
6897 | 6984 | ||
6985 | mlog(0, "reflink xattr buckets %llu len %u\n", | ||
6986 | (unsigned long long)blkno, len); | ||
6987 | |||
6898 | ocfs2_init_xattr_tree_extent_tree(&et, | 6988 | ocfs2_init_xattr_tree_extent_tree(&et, |
6899 | INODE_CACHE(args->reflink->new_inode), | 6989 | INODE_CACHE(args->reflink->new_inode), |
6900 | args->new_blk_bh); | 6990 | args->new_blk_bh); |
@@ -6914,32 +7004,12 @@ static int ocfs2_reflink_xattr_rec(struct inode *inode, | |||
6914 | goto out; | 7004 | goto out; |
6915 | } | 7005 | } |
6916 | 7006 | ||
6917 | ret = ocfs2_claim_clusters(handle, data_ac, | 7007 | ret = ocfs2_reflink_xattr_buckets(handle, inode, args, &et, |
6918 | len, &p_cluster, &num_clusters); | 7008 | meta_ac, data_ac, |
6919 | if (ret) { | 7009 | blkno, cpos, len); |
6920 | mlog_errno(ret); | ||
6921 | goto out_commit; | ||
6922 | } | ||
6923 | |||
6924 | new_blkno = ocfs2_clusters_to_blocks(osb->sb, p_cluster); | ||
6925 | |||
6926 | mlog(0, "reflink xattr buckets %llu to %llu, len %u\n", | ||
6927 | (unsigned long long)blkno, (unsigned long long)new_blkno, len); | ||
6928 | ret = ocfs2_reflink_xattr_buckets(handle, blkno, new_blkno, len, | ||
6929 | meta_ac, data_ac, args); | ||
6930 | if (ret) { | ||
6931 | mlog_errno(ret); | ||
6932 | goto out_commit; | ||
6933 | } | ||
6934 | |||
6935 | mlog(0, "insert new xattr extent rec start %llu len %u to %u\n", | ||
6936 | (unsigned long long)new_blkno, len, cpos); | ||
6937 | ret = ocfs2_insert_extent(handle, &et, cpos, new_blkno, | ||
6938 | len, 0, meta_ac); | ||
6939 | if (ret) | 7010 | if (ret) |
6940 | mlog_errno(ret); | 7011 | mlog_errno(ret); |
6941 | 7012 | ||
6942 | out_commit: | ||
6943 | ocfs2_commit_trans(osb, handle); | 7013 | ocfs2_commit_trans(osb, handle); |
6944 | 7014 | ||
6945 | out: | 7015 | out: |
@@ -110,7 +110,7 @@ static long do_sys_truncate(const char __user *pathname, loff_t length) | |||
110 | 110 | ||
111 | error = locks_verify_truncate(inode, NULL, length); | 111 | error = locks_verify_truncate(inode, NULL, length); |
112 | if (!error) | 112 | if (!error) |
113 | error = security_path_truncate(&path, length, 0); | 113 | error = security_path_truncate(&path); |
114 | if (!error) | 114 | if (!error) |
115 | error = do_truncate(path.dentry, length, 0, NULL); | 115 | error = do_truncate(path.dentry, length, 0, NULL); |
116 | 116 | ||
@@ -165,8 +165,7 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) | |||
165 | 165 | ||
166 | error = locks_verify_truncate(inode, file, length); | 166 | error = locks_verify_truncate(inode, file, length); |
167 | if (!error) | 167 | if (!error) |
168 | error = security_path_truncate(&file->f_path, length, | 168 | error = security_path_truncate(&file->f_path); |
169 | ATTR_MTIME|ATTR_CTIME); | ||
170 | if (!error) | 169 | if (!error) |
171 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); | 170 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); |
172 | out_putf: | 171 | out_putf: |
@@ -367,7 +366,7 @@ SYSCALL_DEFINE1(chdir, const char __user *, filename) | |||
367 | if (error) | 366 | if (error) |
368 | goto out; | 367 | goto out; |
369 | 368 | ||
370 | error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); | 369 | error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); |
371 | if (error) | 370 | if (error) |
372 | goto dput_and_out; | 371 | goto dput_and_out; |
373 | 372 | ||
@@ -396,7 +395,7 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd) | |||
396 | if (!S_ISDIR(inode->i_mode)) | 395 | if (!S_ISDIR(inode->i_mode)) |
397 | goto out_putf; | 396 | goto out_putf; |
398 | 397 | ||
399 | error = inode_permission(inode, MAY_EXEC | MAY_ACCESS); | 398 | error = inode_permission(inode, MAY_EXEC | MAY_CHDIR); |
400 | if (!error) | 399 | if (!error) |
401 | set_fs_pwd(current->fs, &file->f_path); | 400 | set_fs_pwd(current->fs, &file->f_path); |
402 | out_putf: | 401 | out_putf: |
@@ -414,7 +413,7 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename) | |||
414 | if (error) | 413 | if (error) |
415 | goto out; | 414 | goto out; |
416 | 415 | ||
417 | error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); | 416 | error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_CHDIR); |
418 | if (error) | 417 | if (error) |
419 | goto dput_and_out; | 418 | goto dput_and_out; |
420 | 419 | ||
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 5dcd4b0c5533..72c52656dc2e 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -459,7 +459,6 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
459 | } | 459 | } |
460 | 460 | ||
461 | /* everything is up and running, commence */ | 461 | /* everything is up and running, commence */ |
462 | INIT_RCU_HEAD(&p->rcu_head); | ||
463 | rcu_assign_pointer(ptbl->part[partno], p); | 462 | rcu_assign_pointer(ptbl->part[partno], p); |
464 | 463 | ||
465 | /* suppress uevent if the disk supresses it */ | 464 | /* suppress uevent if the disk supresses it */ |
diff --git a/fs/partitions/ibm.c b/fs/partitions/ibm.c index 3e73de5967ff..fc8497643fd0 100644 --- a/fs/partitions/ibm.c +++ b/fs/partitions/ibm.c | |||
@@ -74,6 +74,7 @@ int ibm_partition(struct parsed_partitions *state) | |||
74 | } *label; | 74 | } *label; |
75 | unsigned char *data; | 75 | unsigned char *data; |
76 | Sector sect; | 76 | Sector sect; |
77 | sector_t labelsect; | ||
77 | 78 | ||
78 | res = 0; | 79 | res = 0; |
79 | blocksize = bdev_logical_block_size(bdev); | 80 | blocksize = bdev_logical_block_size(bdev); |
@@ -98,10 +99,19 @@ int ibm_partition(struct parsed_partitions *state) | |||
98 | goto out_freeall; | 99 | goto out_freeall; |
99 | 100 | ||
100 | /* | 101 | /* |
102 | * Special case for FBA disks: label sector does not depend on | ||
103 | * blocksize. | ||
104 | */ | ||
105 | if ((info->cu_type == 0x6310 && info->dev_type == 0x9336) || | ||
106 | (info->cu_type == 0x3880 && info->dev_type == 0x3370)) | ||
107 | labelsect = info->label_block; | ||
108 | else | ||
109 | labelsect = info->label_block * (blocksize >> 9); | ||
110 | |||
111 | /* | ||
101 | * Get volume label, extract name and type. | 112 | * Get volume label, extract name and type. |
102 | */ | 113 | */ |
103 | data = read_part_sector(state, info->label_block*(blocksize/512), | 114 | data = read_part_sector(state, labelsect, §); |
104 | §); | ||
105 | if (data == NULL) | 115 | if (data == NULL) |
106 | goto out_readerr; | 116 | goto out_readerr; |
107 | 117 | ||
diff --git a/fs/proc/array.c b/fs/proc/array.c index 9b58d38bc911..fff6572676ae 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -176,7 +176,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns, | |||
176 | if (tracer) | 176 | if (tracer) |
177 | tpid = task_pid_nr_ns(tracer, ns); | 177 | tpid = task_pid_nr_ns(tracer, ns); |
178 | } | 178 | } |
179 | cred = get_cred((struct cred *) __task_cred(p)); | 179 | cred = get_task_cred(p); |
180 | seq_printf(m, | 180 | seq_printf(m, |
181 | "State:\t%s\n" | 181 | "State:\t%s\n" |
182 | "Tgid:\t%d\n" | 182 | "Tgid:\t%d\n" |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 12c233da1b6b..ef72b1699429 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
@@ -132,6 +132,22 @@ static __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_state_lock); | |||
132 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_data_lock); | 132 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(dq_data_lock); |
133 | EXPORT_SYMBOL(dq_data_lock); | 133 | EXPORT_SYMBOL(dq_data_lock); |
134 | 134 | ||
135 | void __quota_error(struct super_block *sb, const char *func, | ||
136 | const char *fmt, ...) | ||
137 | { | ||
138 | va_list args; | ||
139 | |||
140 | if (printk_ratelimit()) { | ||
141 | va_start(args, fmt); | ||
142 | printk(KERN_ERR "Quota error (device %s): %s: ", | ||
143 | sb->s_id, func); | ||
144 | vprintk(fmt, args); | ||
145 | printk("\n"); | ||
146 | va_end(args); | ||
147 | } | ||
148 | } | ||
149 | EXPORT_SYMBOL(__quota_error); | ||
150 | |||
135 | #if defined(CONFIG_QUOTA_DEBUG) || defined(CONFIG_PRINT_QUOTA_WARNING) | 151 | #if defined(CONFIG_QUOTA_DEBUG) || defined(CONFIG_PRINT_QUOTA_WARNING) |
136 | static char *quotatypes[] = INITQFNAMES; | 152 | static char *quotatypes[] = INITQFNAMES; |
137 | #endif | 153 | #endif |
@@ -676,7 +692,7 @@ static void prune_dqcache(int count) | |||
676 | * This is called from kswapd when we think we need some | 692 | * This is called from kswapd when we think we need some |
677 | * more memory | 693 | * more memory |
678 | */ | 694 | */ |
679 | static int shrink_dqcache_memory(int nr, gfp_t gfp_mask) | 695 | static int shrink_dqcache_memory(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
680 | { | 696 | { |
681 | if (nr) { | 697 | if (nr) { |
682 | spin_lock(&dq_list_lock); | 698 | spin_lock(&dq_list_lock); |
@@ -705,11 +721,8 @@ void dqput(struct dquot *dquot) | |||
705 | return; | 721 | return; |
706 | #ifdef CONFIG_QUOTA_DEBUG | 722 | #ifdef CONFIG_QUOTA_DEBUG |
707 | if (!atomic_read(&dquot->dq_count)) { | 723 | if (!atomic_read(&dquot->dq_count)) { |
708 | printk("VFS: dqput: trying to free free dquot\n"); | 724 | quota_error(dquot->dq_sb, "trying to free free dquot of %s %d", |
709 | printk("VFS: device %s, dquot of %s %d\n", | 725 | quotatypes[dquot->dq_type], dquot->dq_id); |
710 | dquot->dq_sb->s_id, | ||
711 | quotatypes[dquot->dq_type], | ||
712 | dquot->dq_id); | ||
713 | BUG(); | 726 | BUG(); |
714 | } | 727 | } |
715 | #endif | 728 | #endif |
@@ -732,9 +745,9 @@ we_slept: | |||
732 | /* Commit dquot before releasing */ | 745 | /* Commit dquot before releasing */ |
733 | ret = dquot->dq_sb->dq_op->write_dquot(dquot); | 746 | ret = dquot->dq_sb->dq_op->write_dquot(dquot); |
734 | if (ret < 0) { | 747 | if (ret < 0) { |
735 | printk(KERN_ERR "VFS: cannot write quota structure on " | 748 | quota_error(dquot->dq_sb, "Can't write quota structure" |
736 | "device %s (error %d). Quota may get out of " | 749 | " (error %d). Quota may get out of sync!", |
737 | "sync!\n", dquot->dq_sb->s_id, ret); | 750 | ret); |
738 | /* | 751 | /* |
739 | * We clear dirty bit anyway, so that we avoid | 752 | * We clear dirty bit anyway, so that we avoid |
740 | * infinite loop here | 753 | * infinite loop here |
@@ -914,9 +927,9 @@ static void add_dquot_ref(struct super_block *sb, int type) | |||
914 | 927 | ||
915 | #ifdef CONFIG_QUOTA_DEBUG | 928 | #ifdef CONFIG_QUOTA_DEBUG |
916 | if (reserved) { | 929 | if (reserved) { |
917 | printk(KERN_WARNING "VFS (%s): Writes happened before quota" | 930 | quota_error(sb, "Writes happened before quota was turned on " |
918 | " was turned on thus quota information is probably " | 931 | "thus quota information is probably inconsistent. " |
919 | "inconsistent. Please run quotacheck(8).\n", sb->s_id); | 932 | "Please run quotacheck(8)"); |
920 | } | 933 | } |
921 | #endif | 934 | #endif |
922 | } | 935 | } |
@@ -947,7 +960,9 @@ static int remove_inode_dquot_ref(struct inode *inode, int type, | |||
947 | if (dqput_blocks(dquot)) { | 960 | if (dqput_blocks(dquot)) { |
948 | #ifdef CONFIG_QUOTA_DEBUG | 961 | #ifdef CONFIG_QUOTA_DEBUG |
949 | if (atomic_read(&dquot->dq_count) != 1) | 962 | if (atomic_read(&dquot->dq_count) != 1) |
950 | printk(KERN_WARNING "VFS: Adding dquot with dq_count %d to dispose list.\n", atomic_read(&dquot->dq_count)); | 963 | quota_error(inode->i_sb, "Adding dquot with " |
964 | "dq_count %d to dispose list", | ||
965 | atomic_read(&dquot->dq_count)); | ||
951 | #endif | 966 | #endif |
952 | spin_lock(&dq_list_lock); | 967 | spin_lock(&dq_list_lock); |
953 | /* As dquot must have currently users it can't be on | 968 | /* As dquot must have currently users it can't be on |
@@ -986,6 +1001,7 @@ static void remove_dquot_ref(struct super_block *sb, int type, | |||
986 | struct list_head *tofree_head) | 1001 | struct list_head *tofree_head) |
987 | { | 1002 | { |
988 | struct inode *inode; | 1003 | struct inode *inode; |
1004 | int reserved = 0; | ||
989 | 1005 | ||
990 | spin_lock(&inode_lock); | 1006 | spin_lock(&inode_lock); |
991 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { | 1007 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { |
@@ -995,10 +1011,20 @@ static void remove_dquot_ref(struct super_block *sb, int type, | |||
995 | * only quota pointers and these have separate locking | 1011 | * only quota pointers and these have separate locking |
996 | * (dqptr_sem). | 1012 | * (dqptr_sem). |
997 | */ | 1013 | */ |
998 | if (!IS_NOQUOTA(inode)) | 1014 | if (!IS_NOQUOTA(inode)) { |
1015 | if (unlikely(inode_get_rsv_space(inode) > 0)) | ||
1016 | reserved = 1; | ||
999 | remove_inode_dquot_ref(inode, type, tofree_head); | 1017 | remove_inode_dquot_ref(inode, type, tofree_head); |
1018 | } | ||
1000 | } | 1019 | } |
1001 | spin_unlock(&inode_lock); | 1020 | spin_unlock(&inode_lock); |
1021 | #ifdef CONFIG_QUOTA_DEBUG | ||
1022 | if (reserved) { | ||
1023 | printk(KERN_WARNING "VFS (%s): Writes happened after quota" | ||
1024 | " was disabled thus quota information is probably " | ||
1025 | "inconsistent. Please run quotacheck(8).\n", sb->s_id); | ||
1026 | } | ||
1027 | #endif | ||
1002 | } | 1028 | } |
1003 | 1029 | ||
1004 | /* Gather all references from inodes and drop them */ | 1030 | /* Gather all references from inodes and drop them */ |
@@ -1304,6 +1330,15 @@ static int info_bdq_free(struct dquot *dquot, qsize_t space) | |||
1304 | return QUOTA_NL_NOWARN; | 1330 | return QUOTA_NL_NOWARN; |
1305 | } | 1331 | } |
1306 | 1332 | ||
1333 | static int dquot_active(const struct inode *inode) | ||
1334 | { | ||
1335 | struct super_block *sb = inode->i_sb; | ||
1336 | |||
1337 | if (IS_NOQUOTA(inode)) | ||
1338 | return 0; | ||
1339 | return sb_any_quota_loaded(sb) & ~sb_any_quota_suspended(sb); | ||
1340 | } | ||
1341 | |||
1307 | /* | 1342 | /* |
1308 | * Initialize quota pointers in inode | 1343 | * Initialize quota pointers in inode |
1309 | * | 1344 | * |
@@ -1323,7 +1358,7 @@ static void __dquot_initialize(struct inode *inode, int type) | |||
1323 | 1358 | ||
1324 | /* First test before acquiring mutex - solves deadlocks when we | 1359 | /* First test before acquiring mutex - solves deadlocks when we |
1325 | * re-enter the quota code and are already holding the mutex */ | 1360 | * re-enter the quota code and are already holding the mutex */ |
1326 | if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode)) | 1361 | if (!dquot_active(inode)) |
1327 | return; | 1362 | return; |
1328 | 1363 | ||
1329 | /* First get references to structures we might need. */ | 1364 | /* First get references to structures we might need. */ |
@@ -1507,7 +1542,7 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags) | |||
1507 | * First test before acquiring mutex - solves deadlocks when we | 1542 | * First test before acquiring mutex - solves deadlocks when we |
1508 | * re-enter the quota code and are already holding the mutex | 1543 | * re-enter the quota code and are already holding the mutex |
1509 | */ | 1544 | */ |
1510 | if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode)) { | 1545 | if (!dquot_active(inode)) { |
1511 | inode_incr_space(inode, number, reserve); | 1546 | inode_incr_space(inode, number, reserve); |
1512 | goto out; | 1547 | goto out; |
1513 | } | 1548 | } |
@@ -1559,7 +1594,7 @@ int dquot_alloc_inode(const struct inode *inode) | |||
1559 | 1594 | ||
1560 | /* First test before acquiring mutex - solves deadlocks when we | 1595 | /* First test before acquiring mutex - solves deadlocks when we |
1561 | * re-enter the quota code and are already holding the mutex */ | 1596 | * re-enter the quota code and are already holding the mutex */ |
1562 | if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode)) | 1597 | if (!dquot_active(inode)) |
1563 | return 0; | 1598 | return 0; |
1564 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) | 1599 | for (cnt = 0; cnt < MAXQUOTAS; cnt++) |
1565 | warntype[cnt] = QUOTA_NL_NOWARN; | 1600 | warntype[cnt] = QUOTA_NL_NOWARN; |
@@ -1596,7 +1631,7 @@ int dquot_claim_space_nodirty(struct inode *inode, qsize_t number) | |||
1596 | { | 1631 | { |
1597 | int cnt; | 1632 | int cnt; |
1598 | 1633 | ||
1599 | if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode)) { | 1634 | if (!dquot_active(inode)) { |
1600 | inode_claim_rsv_space(inode, number); | 1635 | inode_claim_rsv_space(inode, number); |
1601 | return 0; | 1636 | return 0; |
1602 | } | 1637 | } |
@@ -1629,7 +1664,7 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags) | |||
1629 | 1664 | ||
1630 | /* First test before acquiring mutex - solves deadlocks when we | 1665 | /* First test before acquiring mutex - solves deadlocks when we |
1631 | * re-enter the quota code and are already holding the mutex */ | 1666 | * re-enter the quota code and are already holding the mutex */ |
1632 | if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode)) { | 1667 | if (!dquot_active(inode)) { |
1633 | inode_decr_space(inode, number, reserve); | 1668 | inode_decr_space(inode, number, reserve); |
1634 | return; | 1669 | return; |
1635 | } | 1670 | } |
@@ -1667,7 +1702,7 @@ void dquot_free_inode(const struct inode *inode) | |||
1667 | 1702 | ||
1668 | /* First test before acquiring mutex - solves deadlocks when we | 1703 | /* First test before acquiring mutex - solves deadlocks when we |
1669 | * re-enter the quota code and are already holding the mutex */ | 1704 | * re-enter the quota code and are already holding the mutex */ |
1670 | if (!sb_any_quota_active(inode->i_sb) || IS_NOQUOTA(inode)) | 1705 | if (!dquot_active(inode)) |
1671 | return; | 1706 | return; |
1672 | 1707 | ||
1673 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); | 1708 | down_read(&sb_dqopt(inode->i_sb)->dqptr_sem); |
@@ -1790,7 +1825,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr) | |||
1790 | struct super_block *sb = inode->i_sb; | 1825 | struct super_block *sb = inode->i_sb; |
1791 | int ret; | 1826 | int ret; |
1792 | 1827 | ||
1793 | if (!sb_any_quota_active(sb) || IS_NOQUOTA(inode)) | 1828 | if (!dquot_active(inode)) |
1794 | return 0; | 1829 | return 0; |
1795 | 1830 | ||
1796 | if (iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) | 1831 | if (iattr->ia_valid & ATTR_UID && iattr->ia_uid != inode->i_uid) |
@@ -1957,7 +1992,7 @@ int dquot_disable(struct super_block *sb, int type, unsigned int flags) | |||
1957 | truncate_inode_pages(&toputinode[cnt]->i_data, | 1992 | truncate_inode_pages(&toputinode[cnt]->i_data, |
1958 | 0); | 1993 | 0); |
1959 | mutex_unlock(&toputinode[cnt]->i_mutex); | 1994 | mutex_unlock(&toputinode[cnt]->i_mutex); |
1960 | mark_inode_dirty(toputinode[cnt]); | 1995 | mark_inode_dirty_sync(toputinode[cnt]); |
1961 | } | 1996 | } |
1962 | mutex_unlock(&dqopt->dqonoff_mutex); | 1997 | mutex_unlock(&dqopt->dqonoff_mutex); |
1963 | } | 1998 | } |
@@ -2270,7 +2305,7 @@ static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di) | |||
2270 | memset(di, 0, sizeof(*di)); | 2305 | memset(di, 0, sizeof(*di)); |
2271 | di->d_version = FS_DQUOT_VERSION; | 2306 | di->d_version = FS_DQUOT_VERSION; |
2272 | di->d_flags = dquot->dq_type == USRQUOTA ? | 2307 | di->d_flags = dquot->dq_type == USRQUOTA ? |
2273 | XFS_USER_QUOTA : XFS_GROUP_QUOTA; | 2308 | FS_USER_QUOTA : FS_GROUP_QUOTA; |
2274 | di->d_id = dquot->dq_id; | 2309 | di->d_id = dquot->dq_id; |
2275 | 2310 | ||
2276 | spin_lock(&dq_data_lock); | 2311 | spin_lock(&dq_data_lock); |
diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c index 24f03407eeb5..9e48874eabcc 100644 --- a/fs/quota/quota_tree.c +++ b/fs/quota/quota_tree.c | |||
@@ -65,8 +65,7 @@ static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) | |||
65 | ret = sb->s_op->quota_write(sb, info->dqi_type, buf, | 65 | ret = sb->s_op->quota_write(sb, info->dqi_type, buf, |
66 | info->dqi_usable_bs, blk << info->dqi_blocksize_bits); | 66 | info->dqi_usable_bs, blk << info->dqi_blocksize_bits); |
67 | if (ret != info->dqi_usable_bs) { | 67 | if (ret != info->dqi_usable_bs) { |
68 | q_warn(KERN_WARNING "VFS: dquota write failed on " | 68 | quota_error(sb, "dquota write failed"); |
69 | "dev %s\n", sb->s_id); | ||
70 | if (ret >= 0) | 69 | if (ret >= 0) |
71 | ret = -EIO; | 70 | ret = -EIO; |
72 | } | 71 | } |
@@ -160,9 +159,8 @@ static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, | |||
160 | dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0); | 159 | dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0); |
161 | /* No matter whether write succeeds block is out of list */ | 160 | /* No matter whether write succeeds block is out of list */ |
162 | if (write_blk(info, blk, buf) < 0) | 161 | if (write_blk(info, blk, buf) < 0) |
163 | q_warn(KERN_ERR | 162 | quota_error(info->dqi_sb, "Can't write block (%u) " |
164 | "VFS: Can't write block (%u) with free entries.\n", | 163 | "with free entries", blk); |
165 | blk); | ||
166 | return 0; | 164 | return 0; |
167 | out_buf: | 165 | out_buf: |
168 | kfree(tmpbuf); | 166 | kfree(tmpbuf); |
@@ -252,9 +250,8 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, | |||
252 | if (le16_to_cpu(dh->dqdh_entries) + 1 >= qtree_dqstr_in_blk(info)) { | 250 | if (le16_to_cpu(dh->dqdh_entries) + 1 >= qtree_dqstr_in_blk(info)) { |
253 | *err = remove_free_dqentry(info, buf, blk); | 251 | *err = remove_free_dqentry(info, buf, blk); |
254 | if (*err < 0) { | 252 | if (*err < 0) { |
255 | q_warn(KERN_ERR "VFS: find_free_dqentry(): Can't " | 253 | quota_error(dquot->dq_sb, "Can't remove block (%u) " |
256 | "remove block (%u) from entry free list.\n", | 254 | "from entry free list", blk); |
257 | blk); | ||
258 | goto out_buf; | 255 | goto out_buf; |
259 | } | 256 | } |
260 | } | 257 | } |
@@ -268,16 +265,15 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, | |||
268 | } | 265 | } |
269 | #ifdef __QUOTA_QT_PARANOIA | 266 | #ifdef __QUOTA_QT_PARANOIA |
270 | if (i == qtree_dqstr_in_blk(info)) { | 267 | if (i == qtree_dqstr_in_blk(info)) { |
271 | printk(KERN_ERR "VFS: find_free_dqentry(): Data block full " | 268 | quota_error(dquot->dq_sb, "Data block full but it shouldn't"); |
272 | "but it shouldn't.\n"); | ||
273 | *err = -EIO; | 269 | *err = -EIO; |
274 | goto out_buf; | 270 | goto out_buf; |
275 | } | 271 | } |
276 | #endif | 272 | #endif |
277 | *err = write_blk(info, blk, buf); | 273 | *err = write_blk(info, blk, buf); |
278 | if (*err < 0) { | 274 | if (*err < 0) { |
279 | q_warn(KERN_ERR "VFS: find_free_dqentry(): Can't write quota " | 275 | quota_error(dquot->dq_sb, "Can't write quota data block %u", |
280 | "data block %u.\n", blk); | 276 | blk); |
281 | goto out_buf; | 277 | goto out_buf; |
282 | } | 278 | } |
283 | dquot->dq_off = (blk << info->dqi_blocksize_bits) + | 279 | dquot->dq_off = (blk << info->dqi_blocksize_bits) + |
@@ -311,8 +307,8 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, | |||
311 | } else { | 307 | } else { |
312 | ret = read_blk(info, *treeblk, buf); | 308 | ret = read_blk(info, *treeblk, buf); |
313 | if (ret < 0) { | 309 | if (ret < 0) { |
314 | q_warn(KERN_ERR "VFS: Can't read tree quota block " | 310 | quota_error(dquot->dq_sb, "Can't read tree quota " |
315 | "%u.\n", *treeblk); | 311 | "block %u", *treeblk); |
316 | goto out_buf; | 312 | goto out_buf; |
317 | } | 313 | } |
318 | } | 314 | } |
@@ -323,9 +319,9 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, | |||
323 | if (depth == info->dqi_qtree_depth - 1) { | 319 | if (depth == info->dqi_qtree_depth - 1) { |
324 | #ifdef __QUOTA_QT_PARANOIA | 320 | #ifdef __QUOTA_QT_PARANOIA |
325 | if (newblk) { | 321 | if (newblk) { |
326 | printk(KERN_ERR "VFS: Inserting already present quota " | 322 | quota_error(dquot->dq_sb, "Inserting already present " |
327 | "entry (block %u).\n", | 323 | "quota entry (block %u)", |
328 | le32_to_cpu(ref[get_index(info, | 324 | le32_to_cpu(ref[get_index(info, |
329 | dquot->dq_id, depth)])); | 325 | dquot->dq_id, depth)])); |
330 | ret = -EIO; | 326 | ret = -EIO; |
331 | goto out_buf; | 327 | goto out_buf; |
@@ -373,8 +369,8 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
373 | if (!dquot->dq_off) { | 369 | if (!dquot->dq_off) { |
374 | ret = dq_insert_tree(info, dquot); | 370 | ret = dq_insert_tree(info, dquot); |
375 | if (ret < 0) { | 371 | if (ret < 0) { |
376 | q_warn(KERN_ERR "VFS: Error %zd occurred while " | 372 | quota_error(sb, "Error %zd occurred while creating " |
377 | "creating quota.\n", ret); | 373 | "quota", ret); |
378 | kfree(ddquot); | 374 | kfree(ddquot); |
379 | return ret; | 375 | return ret; |
380 | } | 376 | } |
@@ -385,8 +381,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
385 | ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size, | 381 | ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size, |
386 | dquot->dq_off); | 382 | dquot->dq_off); |
387 | if (ret != info->dqi_entry_size) { | 383 | if (ret != info->dqi_entry_size) { |
388 | q_warn(KERN_WARNING "VFS: dquota write failed on dev %s\n", | 384 | quota_error(sb, "dquota write failed"); |
389 | sb->s_id); | ||
390 | if (ret >= 0) | 385 | if (ret >= 0) |
391 | ret = -ENOSPC; | 386 | ret = -ENOSPC; |
392 | } else { | 387 | } else { |
@@ -410,14 +405,15 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, | |||
410 | if (!buf) | 405 | if (!buf) |
411 | return -ENOMEM; | 406 | return -ENOMEM; |
412 | if (dquot->dq_off >> info->dqi_blocksize_bits != blk) { | 407 | if (dquot->dq_off >> info->dqi_blocksize_bits != blk) { |
413 | q_warn(KERN_ERR "VFS: Quota structure has offset to other " | 408 | quota_error(dquot->dq_sb, "Quota structure has offset to " |
414 | "block (%u) than it should (%u).\n", blk, | 409 | "other block (%u) than it should (%u)", blk, |
415 | (uint)(dquot->dq_off >> info->dqi_blocksize_bits)); | 410 | (uint)(dquot->dq_off >> info->dqi_blocksize_bits)); |
416 | goto out_buf; | 411 | goto out_buf; |
417 | } | 412 | } |
418 | ret = read_blk(info, blk, buf); | 413 | ret = read_blk(info, blk, buf); |
419 | if (ret < 0) { | 414 | if (ret < 0) { |
420 | q_warn(KERN_ERR "VFS: Can't read quota data block %u\n", blk); | 415 | quota_error(dquot->dq_sb, "Can't read quota data block %u", |
416 | blk); | ||
421 | goto out_buf; | 417 | goto out_buf; |
422 | } | 418 | } |
423 | dh = (struct qt_disk_dqdbheader *)buf; | 419 | dh = (struct qt_disk_dqdbheader *)buf; |
@@ -427,8 +423,8 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, | |||
427 | if (ret >= 0) | 423 | if (ret >= 0) |
428 | ret = put_free_dqblk(info, buf, blk); | 424 | ret = put_free_dqblk(info, buf, blk); |
429 | if (ret < 0) { | 425 | if (ret < 0) { |
430 | q_warn(KERN_ERR "VFS: Can't move quota data block (%u) " | 426 | quota_error(dquot->dq_sb, "Can't move quota data block " |
431 | "to free list.\n", blk); | 427 | "(%u) to free list", blk); |
432 | goto out_buf; | 428 | goto out_buf; |
433 | } | 429 | } |
434 | } else { | 430 | } else { |
@@ -440,15 +436,15 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, | |||
440 | /* Insert will write block itself */ | 436 | /* Insert will write block itself */ |
441 | ret = insert_free_dqentry(info, buf, blk); | 437 | ret = insert_free_dqentry(info, buf, blk); |
442 | if (ret < 0) { | 438 | if (ret < 0) { |
443 | q_warn(KERN_ERR "VFS: Can't insert quota data " | 439 | quota_error(dquot->dq_sb, "Can't insert quota " |
444 | "block (%u) to free entry list.\n", blk); | 440 | "data block (%u) to free entry list", blk); |
445 | goto out_buf; | 441 | goto out_buf; |
446 | } | 442 | } |
447 | } else { | 443 | } else { |
448 | ret = write_blk(info, blk, buf); | 444 | ret = write_blk(info, blk, buf); |
449 | if (ret < 0) { | 445 | if (ret < 0) { |
450 | q_warn(KERN_ERR "VFS: Can't write quota data " | 446 | quota_error(dquot->dq_sb, "Can't write quota " |
451 | "block %u\n", blk); | 447 | "data block %u", blk); |
452 | goto out_buf; | 448 | goto out_buf; |
453 | } | 449 | } |
454 | } | 450 | } |
@@ -472,7 +468,8 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, | |||
472 | return -ENOMEM; | 468 | return -ENOMEM; |
473 | ret = read_blk(info, *blk, buf); | 469 | ret = read_blk(info, *blk, buf); |
474 | if (ret < 0) { | 470 | if (ret < 0) { |
475 | q_warn(KERN_ERR "VFS: Can't read quota data block %u\n", *blk); | 471 | quota_error(dquot->dq_sb, "Can't read quota data " |
472 | "block %u", blk); | ||
476 | goto out_buf; | 473 | goto out_buf; |
477 | } | 474 | } |
478 | newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); | 475 | newblk = le32_to_cpu(ref[get_index(info, dquot->dq_id, depth)]); |
@@ -496,8 +493,8 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, | |||
496 | } else { | 493 | } else { |
497 | ret = write_blk(info, *blk, buf); | 494 | ret = write_blk(info, *blk, buf); |
498 | if (ret < 0) | 495 | if (ret < 0) |
499 | q_warn(KERN_ERR "VFS: Can't write quota tree " | 496 | quota_error(dquot->dq_sb, "Can't write quota " |
500 | "block %u.\n", *blk); | 497 | "tree block %u", blk); |
501 | } | 498 | } |
502 | } | 499 | } |
503 | out_buf: | 500 | out_buf: |
@@ -529,7 +526,8 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, | |||
529 | return -ENOMEM; | 526 | return -ENOMEM; |
530 | ret = read_blk(info, blk, buf); | 527 | ret = read_blk(info, blk, buf); |
531 | if (ret < 0) { | 528 | if (ret < 0) { |
532 | q_warn(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk); | 529 | quota_error(dquot->dq_sb, "Can't read quota tree " |
530 | "block %u", blk); | ||
533 | goto out_buf; | 531 | goto out_buf; |
534 | } | 532 | } |
535 | ddquot = buf + sizeof(struct qt_disk_dqdbheader); | 533 | ddquot = buf + sizeof(struct qt_disk_dqdbheader); |
@@ -539,8 +537,8 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, | |||
539 | ddquot += info->dqi_entry_size; | 537 | ddquot += info->dqi_entry_size; |
540 | } | 538 | } |
541 | if (i == qtree_dqstr_in_blk(info)) { | 539 | if (i == qtree_dqstr_in_blk(info)) { |
542 | q_warn(KERN_ERR "VFS: Quota for id %u referenced " | 540 | quota_error(dquot->dq_sb, "Quota for id %u referenced " |
543 | "but not present.\n", dquot->dq_id); | 541 | "but not present", dquot->dq_id); |
544 | ret = -EIO; | 542 | ret = -EIO; |
545 | goto out_buf; | 543 | goto out_buf; |
546 | } else { | 544 | } else { |
@@ -564,7 +562,8 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, | |||
564 | return -ENOMEM; | 562 | return -ENOMEM; |
565 | ret = read_blk(info, blk, buf); | 563 | ret = read_blk(info, blk, buf); |
566 | if (ret < 0) { | 564 | if (ret < 0) { |
567 | q_warn(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk); | 565 | quota_error(dquot->dq_sb, "Can't read quota tree block %u", |
566 | blk); | ||
568 | goto out_buf; | 567 | goto out_buf; |
569 | } | 568 | } |
570 | ret = 0; | 569 | ret = 0; |
@@ -598,7 +597,7 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
598 | #ifdef __QUOTA_QT_PARANOIA | 597 | #ifdef __QUOTA_QT_PARANOIA |
599 | /* Invalidated quota? */ | 598 | /* Invalidated quota? */ |
600 | if (!sb_dqopt(dquot->dq_sb)->files[type]) { | 599 | if (!sb_dqopt(dquot->dq_sb)->files[type]) { |
601 | printk(KERN_ERR "VFS: Quota invalidated while reading!\n"); | 600 | quota_error(sb, "Quota invalidated while reading!"); |
602 | return -EIO; | 601 | return -EIO; |
603 | } | 602 | } |
604 | #endif | 603 | #endif |
@@ -607,8 +606,8 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
607 | offset = find_dqentry(info, dquot); | 606 | offset = find_dqentry(info, dquot); |
608 | if (offset <= 0) { /* Entry not present? */ | 607 | if (offset <= 0) { /* Entry not present? */ |
609 | if (offset < 0) | 608 | if (offset < 0) |
610 | q_warn(KERN_ERR "VFS: Can't read quota " | 609 | quota_error(sb, "Can't read quota structure " |
611 | "structure for id %u.\n", dquot->dq_id); | 610 | "for id %u", dquot->dq_id); |
612 | dquot->dq_off = 0; | 611 | dquot->dq_off = 0; |
613 | set_bit(DQ_FAKE_B, &dquot->dq_flags); | 612 | set_bit(DQ_FAKE_B, &dquot->dq_flags); |
614 | memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); | 613 | memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); |
@@ -625,8 +624,8 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) | |||
625 | if (ret != info->dqi_entry_size) { | 624 | if (ret != info->dqi_entry_size) { |
626 | if (ret >= 0) | 625 | if (ret >= 0) |
627 | ret = -EIO; | 626 | ret = -EIO; |
628 | q_warn(KERN_ERR "VFS: Error while reading quota " | 627 | quota_error(sb, "Error while reading quota structure for id %u", |
629 | "structure for id %u.\n", dquot->dq_id); | 628 | dquot->dq_id); |
630 | set_bit(DQ_FAKE_B, &dquot->dq_flags); | 629 | set_bit(DQ_FAKE_B, &dquot->dq_flags); |
631 | memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); | 630 | memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); |
632 | kfree(ddquot); | 631 | kfree(ddquot); |
diff --git a/fs/quota/quota_tree.h b/fs/quota/quota_tree.h index ccc3e71fb1d8..a1ab8db81a51 100644 --- a/fs/quota/quota_tree.h +++ b/fs/quota/quota_tree.h | |||
@@ -22,10 +22,4 @@ struct qt_disk_dqdbheader { | |||
22 | 22 | ||
23 | #define QT_TREEOFF 1 /* Offset of tree in file in blocks */ | 23 | #define QT_TREEOFF 1 /* Offset of tree in file in blocks */ |
24 | 24 | ||
25 | #define q_warn(fmt, args...) \ | ||
26 | do { \ | ||
27 | if (printk_ratelimit()) \ | ||
28 | printk(fmt, ## args); \ | ||
29 | } while(0) | ||
30 | |||
31 | #endif /* _LINUX_QUOTAIO_TREE_H */ | 25 | #endif /* _LINUX_QUOTAIO_TREE_H */ |
diff --git a/fs/quota/quota_v1.c b/fs/quota/quota_v1.c index 4af344c5852a..34b37a67bb16 100644 --- a/fs/quota/quota_v1.c +++ b/fs/quota/quota_v1.c | |||
@@ -95,8 +95,7 @@ static int v1_commit_dqblk(struct dquot *dquot) | |||
95 | (char *)&dqblk, sizeof(struct v1_disk_dqblk), | 95 | (char *)&dqblk, sizeof(struct v1_disk_dqblk), |
96 | v1_dqoff(dquot->dq_id)); | 96 | v1_dqoff(dquot->dq_id)); |
97 | if (ret != sizeof(struct v1_disk_dqblk)) { | 97 | if (ret != sizeof(struct v1_disk_dqblk)) { |
98 | printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", | 98 | quota_error(dquot->dq_sb, "dquota write failed"); |
99 | dquot->dq_sb->s_id); | ||
100 | if (ret >= 0) | 99 | if (ret >= 0) |
101 | ret = -EIO; | 100 | ret = -EIO; |
102 | goto out; | 101 | goto out; |
diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c index 135206af1458..65444d29406b 100644 --- a/fs/quota/quota_v2.c +++ b/fs/quota/quota_v2.c | |||
@@ -63,9 +63,8 @@ static int v2_read_header(struct super_block *sb, int type, | |||
63 | size = sb->s_op->quota_read(sb, type, (char *)dqhead, | 63 | size = sb->s_op->quota_read(sb, type, (char *)dqhead, |
64 | sizeof(struct v2_disk_dqheader), 0); | 64 | sizeof(struct v2_disk_dqheader), 0); |
65 | if (size != sizeof(struct v2_disk_dqheader)) { | 65 | if (size != sizeof(struct v2_disk_dqheader)) { |
66 | q_warn(KERN_WARNING "quota_v2: Failed header read:" | 66 | quota_error(sb, "Failed header read: expected=%zd got=%zd", |
67 | " expected=%zd got=%zd\n", | 67 | sizeof(struct v2_disk_dqheader), size); |
68 | sizeof(struct v2_disk_dqheader), size); | ||
69 | return 0; | 68 | return 0; |
70 | } | 69 | } |
71 | return 1; | 70 | return 1; |
@@ -106,8 +105,7 @@ static int v2_read_file_info(struct super_block *sb, int type) | |||
106 | size = sb->s_op->quota_read(sb, type, (char *)&dinfo, | 105 | size = sb->s_op->quota_read(sb, type, (char *)&dinfo, |
107 | sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); | 106 | sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); |
108 | if (size != sizeof(struct v2_disk_dqinfo)) { | 107 | if (size != sizeof(struct v2_disk_dqinfo)) { |
109 | q_warn(KERN_WARNING "quota_v2: Can't read info structure on device %s.\n", | 108 | quota_error(sb, "Can't read info structure"); |
110 | sb->s_id); | ||
111 | return -1; | 109 | return -1; |
112 | } | 110 | } |
113 | info->dqi_priv = kmalloc(sizeof(struct qtree_mem_dqinfo), GFP_NOFS); | 111 | info->dqi_priv = kmalloc(sizeof(struct qtree_mem_dqinfo), GFP_NOFS); |
@@ -167,8 +165,7 @@ static int v2_write_file_info(struct super_block *sb, int type) | |||
167 | size = sb->s_op->quota_write(sb, type, (char *)&dinfo, | 165 | size = sb->s_op->quota_write(sb, type, (char *)&dinfo, |
168 | sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); | 166 | sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); |
169 | if (size != sizeof(struct v2_disk_dqinfo)) { | 167 | if (size != sizeof(struct v2_disk_dqinfo)) { |
170 | q_warn(KERN_WARNING "Can't write info structure on device %s.\n", | 168 | quota_error(sb, "Can't write info structure"); |
171 | sb->s_id); | ||
172 | return -1; | 169 | return -1; |
173 | } | 170 | } |
174 | return 0; | 171 | return 0; |
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 0f22fdaf54ac..29db72203bde 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
@@ -1221,7 +1221,7 @@ static void init_inode(struct inode *inode, struct treepath *path) | |||
1221 | inode_set_bytes(inode, | 1221 | inode_set_bytes(inode, |
1222 | to_real_used_space(inode, inode->i_blocks, | 1222 | to_real_used_space(inode, inode->i_blocks, |
1223 | SD_V2_SIZE)); | 1223 | SD_V2_SIZE)); |
1224 | /* read persistent inode attributes from sd and initalise | 1224 | /* read persistent inode attributes from sd and initialise |
1225 | generic inode flags from them */ | 1225 | generic inode flags from them */ |
1226 | REISERFS_I(inode)->i_attrs = sd_v2_attrs(sd); | 1226 | REISERFS_I(inode)->i_attrs = sd_v2_attrs(sd); |
1227 | sd_attrs_to_i_attrs(sd_v2_attrs(sd), inode); | 1227 | sd_attrs_to_i_attrs(sd_v2_attrs(sd), inode); |
diff --git a/fs/splice.c b/fs/splice.c index 740e6b9faf7a..efdbfece9932 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -1282,7 +1282,8 @@ static int direct_splice_actor(struct pipe_inode_info *pipe, | |||
1282 | { | 1282 | { |
1283 | struct file *file = sd->u.file; | 1283 | struct file *file = sd->u.file; |
1284 | 1284 | ||
1285 | return do_splice_from(pipe, file, &sd->pos, sd->total_len, sd->flags); | 1285 | return do_splice_from(pipe, file, &file->f_pos, sd->total_len, |
1286 | sd->flags); | ||
1286 | } | 1287 | } |
1287 | 1288 | ||
1288 | /** | 1289 | /** |
@@ -1371,8 +1372,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
1371 | if (off_in) | 1372 | if (off_in) |
1372 | return -ESPIPE; | 1373 | return -ESPIPE; |
1373 | if (off_out) { | 1374 | if (off_out) { |
1374 | if (!out->f_op || !out->f_op->llseek || | 1375 | if (!(out->f_mode & FMODE_PWRITE)) |
1375 | out->f_op->llseek == no_llseek) | ||
1376 | return -EINVAL; | 1376 | return -EINVAL; |
1377 | if (copy_from_user(&offset, off_out, sizeof(loff_t))) | 1377 | if (copy_from_user(&offset, off_out, sizeof(loff_t))) |
1378 | return -EFAULT; | 1378 | return -EFAULT; |
@@ -1392,8 +1392,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
1392 | if (off_out) | 1392 | if (off_out) |
1393 | return -ESPIPE; | 1393 | return -ESPIPE; |
1394 | if (off_in) { | 1394 | if (off_in) { |
1395 | if (!in->f_op || !in->f_op->llseek || | 1395 | if (!(in->f_mode & FMODE_PREAD)) |
1396 | in->f_op->llseek == no_llseek) | ||
1397 | return -EINVAL; | 1396 | return -EINVAL; |
1398 | if (copy_from_user(&offset, off_in, sizeof(loff_t))) | 1397 | if (copy_from_user(&offset, off_in, sizeof(loff_t))) |
1399 | return -EFAULT; | 1398 | return -EFAULT; |
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 1beaa739d0a6..1b27b5688f62 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c | |||
@@ -593,7 +593,8 @@ EXPORT_SYMBOL_GPL(sysfs_add_file_to_group); | |||
593 | * @mode: file permissions. | 593 | * @mode: file permissions. |
594 | * | 594 | * |
595 | */ | 595 | */ |
596 | int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode) | 596 | int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, |
597 | mode_t mode) | ||
597 | { | 598 | { |
598 | struct sysfs_dirent *sd; | 599 | struct sysfs_dirent *sd; |
599 | struct iattr newattrs; | 600 | struct iattr newattrs; |
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c index f71246bebfe4..a7ac78f8e67a 100644 --- a/fs/sysfs/symlink.c +++ b/fs/sysfs/symlink.c | |||
@@ -28,6 +28,7 @@ static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, | |||
28 | struct sysfs_dirent *target_sd = NULL; | 28 | struct sysfs_dirent *target_sd = NULL; |
29 | struct sysfs_dirent *sd = NULL; | 29 | struct sysfs_dirent *sd = NULL; |
30 | struct sysfs_addrm_cxt acxt; | 30 | struct sysfs_addrm_cxt acxt; |
31 | enum kobj_ns_type ns_type; | ||
31 | int error; | 32 | int error; |
32 | 33 | ||
33 | BUG_ON(!name); | 34 | BUG_ON(!name); |
@@ -58,16 +59,29 @@ static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target, | |||
58 | if (!sd) | 59 | if (!sd) |
59 | goto out_put; | 60 | goto out_put; |
60 | 61 | ||
61 | if (sysfs_ns_type(parent_sd)) | 62 | ns_type = sysfs_ns_type(parent_sd); |
63 | if (ns_type) | ||
62 | sd->s_ns = target->ktype->namespace(target); | 64 | sd->s_ns = target->ktype->namespace(target); |
63 | sd->s_symlink.target_sd = target_sd; | 65 | sd->s_symlink.target_sd = target_sd; |
64 | target_sd = NULL; /* reference is now owned by the symlink */ | 66 | target_sd = NULL; /* reference is now owned by the symlink */ |
65 | 67 | ||
66 | sysfs_addrm_start(&acxt, parent_sd); | 68 | sysfs_addrm_start(&acxt, parent_sd); |
67 | if (warn) | 69 | /* Symlinks must be between directories with the same ns_type */ |
68 | error = sysfs_add_one(&acxt, sd); | 70 | if (!ns_type || |
69 | else | 71 | (ns_type == sysfs_ns_type(sd->s_symlink.target_sd->s_parent))) { |
70 | error = __sysfs_add_one(&acxt, sd); | 72 | if (warn) |
73 | error = sysfs_add_one(&acxt, sd); | ||
74 | else | ||
75 | error = __sysfs_add_one(&acxt, sd); | ||
76 | } else { | ||
77 | error = -EINVAL; | ||
78 | WARN(1, KERN_WARNING | ||
79 | "sysfs: symlink across ns_types %s/%s -> %s/%s\n", | ||
80 | parent_sd->s_name, | ||
81 | sd->s_name, | ||
82 | sd->s_symlink.target_sd->s_parent->s_name, | ||
83 | sd->s_symlink.target_sd->s_name); | ||
84 | } | ||
71 | sysfs_addrm_finish(&acxt); | 85 | sysfs_addrm_finish(&acxt); |
72 | 86 | ||
73 | if (error) | 87 | if (error) |
@@ -122,7 +136,7 @@ void sysfs_delete_link(struct kobject *kobj, struct kobject *targ, | |||
122 | { | 136 | { |
123 | const void *ns = NULL; | 137 | const void *ns = NULL; |
124 | spin_lock(&sysfs_assoc_lock); | 138 | spin_lock(&sysfs_assoc_lock); |
125 | if (targ->sd) | 139 | if (targ->sd && sysfs_ns_type(kobj->sd)) |
126 | ns = targ->sd->s_ns; | 140 | ns = targ->sd->s_ns; |
127 | spin_unlock(&sysfs_assoc_lock); | 141 | spin_unlock(&sysfs_assoc_lock); |
128 | sysfs_hash_and_remove(kobj->sd, ns, name); | 142 | sysfs_hash_and_remove(kobj->sd, ns, name); |
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index ad7f67b827ea..0084a33c4c69 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c | |||
@@ -1457,13 +1457,13 @@ struct ubifs_lprops *ubifs_lpt_lookup(struct ubifs_info *c, int lnum) | |||
1457 | shft -= UBIFS_LPT_FANOUT_SHIFT; | 1457 | shft -= UBIFS_LPT_FANOUT_SHIFT; |
1458 | nnode = ubifs_get_nnode(c, nnode, iip); | 1458 | nnode = ubifs_get_nnode(c, nnode, iip); |
1459 | if (IS_ERR(nnode)) | 1459 | if (IS_ERR(nnode)) |
1460 | return ERR_PTR(PTR_ERR(nnode)); | 1460 | return ERR_CAST(nnode); |
1461 | } | 1461 | } |
1462 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); | 1462 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); |
1463 | shft -= UBIFS_LPT_FANOUT_SHIFT; | 1463 | shft -= UBIFS_LPT_FANOUT_SHIFT; |
1464 | pnode = ubifs_get_pnode(c, nnode, iip); | 1464 | pnode = ubifs_get_pnode(c, nnode, iip); |
1465 | if (IS_ERR(pnode)) | 1465 | if (IS_ERR(pnode)) |
1466 | return ERR_PTR(PTR_ERR(pnode)); | 1466 | return ERR_CAST(pnode); |
1467 | iip = (i & (UBIFS_LPT_FANOUT - 1)); | 1467 | iip = (i & (UBIFS_LPT_FANOUT - 1)); |
1468 | dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum, | 1468 | dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum, |
1469 | pnode->lprops[iip].free, pnode->lprops[iip].dirty, | 1469 | pnode->lprops[iip].free, pnode->lprops[iip].dirty, |
@@ -1586,7 +1586,7 @@ struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum) | |||
1586 | nnode = c->nroot; | 1586 | nnode = c->nroot; |
1587 | nnode = dirty_cow_nnode(c, nnode); | 1587 | nnode = dirty_cow_nnode(c, nnode); |
1588 | if (IS_ERR(nnode)) | 1588 | if (IS_ERR(nnode)) |
1589 | return ERR_PTR(PTR_ERR(nnode)); | 1589 | return ERR_CAST(nnode); |
1590 | i = lnum - c->main_first; | 1590 | i = lnum - c->main_first; |
1591 | shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT; | 1591 | shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT; |
1592 | for (h = 1; h < c->lpt_hght; h++) { | 1592 | for (h = 1; h < c->lpt_hght; h++) { |
@@ -1594,19 +1594,19 @@ struct ubifs_lprops *ubifs_lpt_lookup_dirty(struct ubifs_info *c, int lnum) | |||
1594 | shft -= UBIFS_LPT_FANOUT_SHIFT; | 1594 | shft -= UBIFS_LPT_FANOUT_SHIFT; |
1595 | nnode = ubifs_get_nnode(c, nnode, iip); | 1595 | nnode = ubifs_get_nnode(c, nnode, iip); |
1596 | if (IS_ERR(nnode)) | 1596 | if (IS_ERR(nnode)) |
1597 | return ERR_PTR(PTR_ERR(nnode)); | 1597 | return ERR_CAST(nnode); |
1598 | nnode = dirty_cow_nnode(c, nnode); | 1598 | nnode = dirty_cow_nnode(c, nnode); |
1599 | if (IS_ERR(nnode)) | 1599 | if (IS_ERR(nnode)) |
1600 | return ERR_PTR(PTR_ERR(nnode)); | 1600 | return ERR_CAST(nnode); |
1601 | } | 1601 | } |
1602 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); | 1602 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); |
1603 | shft -= UBIFS_LPT_FANOUT_SHIFT; | 1603 | shft -= UBIFS_LPT_FANOUT_SHIFT; |
1604 | pnode = ubifs_get_pnode(c, nnode, iip); | 1604 | pnode = ubifs_get_pnode(c, nnode, iip); |
1605 | if (IS_ERR(pnode)) | 1605 | if (IS_ERR(pnode)) |
1606 | return ERR_PTR(PTR_ERR(pnode)); | 1606 | return ERR_CAST(pnode); |
1607 | pnode = dirty_cow_pnode(c, pnode); | 1607 | pnode = dirty_cow_pnode(c, pnode); |
1608 | if (IS_ERR(pnode)) | 1608 | if (IS_ERR(pnode)) |
1609 | return ERR_PTR(PTR_ERR(pnode)); | 1609 | return ERR_CAST(pnode); |
1610 | iip = (i & (UBIFS_LPT_FANOUT - 1)); | 1610 | iip = (i & (UBIFS_LPT_FANOUT - 1)); |
1611 | dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum, | 1611 | dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum, |
1612 | pnode->lprops[iip].free, pnode->lprops[iip].dirty, | 1612 | pnode->lprops[iip].free, pnode->lprops[iip].dirty, |
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c index 13cb7a4237bf..d12535b7fc78 100644 --- a/fs/ubifs/lpt_commit.c +++ b/fs/ubifs/lpt_commit.c | |||
@@ -646,7 +646,7 @@ static struct ubifs_pnode *pnode_lookup(struct ubifs_info *c, int i) | |||
646 | shft -= UBIFS_LPT_FANOUT_SHIFT; | 646 | shft -= UBIFS_LPT_FANOUT_SHIFT; |
647 | nnode = ubifs_get_nnode(c, nnode, iip); | 647 | nnode = ubifs_get_nnode(c, nnode, iip); |
648 | if (IS_ERR(nnode)) | 648 | if (IS_ERR(nnode)) |
649 | return ERR_PTR(PTR_ERR(nnode)); | 649 | return ERR_CAST(nnode); |
650 | } | 650 | } |
651 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); | 651 | iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); |
652 | return ubifs_get_pnode(c, nnode, iip); | 652 | return ubifs_get_pnode(c, nnode, iip); |
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 109c6ea03bb5..daae9e1f5382 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
@@ -24,7 +24,7 @@ | |||
24 | * This file implements functions needed to recover from unclean un-mounts. | 24 | * This file implements functions needed to recover from unclean un-mounts. |
25 | * When UBIFS is mounted, it checks a flag on the master node to determine if | 25 | * When UBIFS is mounted, it checks a flag on the master node to determine if |
26 | * an un-mount was completed successfully. If not, the process of mounting | 26 | * an un-mount was completed successfully. If not, the process of mounting |
27 | * incorparates additional checking and fixing of on-flash data structures. | 27 | * incorporates additional checking and fixing of on-flash data structures. |
28 | * UBIFS always cleans away all remnants of an unclean un-mount, so that | 28 | * UBIFS always cleans away all remnants of an unclean un-mount, so that |
29 | * errors do not accumulate. However UBIFS defers recovery if it is mounted | 29 | * errors do not accumulate. However UBIFS defers recovery if it is mounted |
30 | * read-only, and the flash is not modified in that case. | 30 | * read-only, and the flash is not modified in that case. |
@@ -1063,8 +1063,21 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c) | |||
1063 | } | 1063 | } |
1064 | err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2); | 1064 | err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2); |
1065 | if (err) { | 1065 | if (err) { |
1066 | if (err == -ENOSPC) | 1066 | /* |
1067 | dbg_err("could not find a dirty LEB"); | 1067 | * There are no dirty or empty LEBs subject to here being |
1068 | * enough for the index. Try to use | ||
1069 | * 'ubifs_find_free_leb_for_idx()', which will return any empty | ||
1070 | * LEBs (ignoring index requirements). If the index then | ||
1071 | * doesn't have enough LEBs the recovery commit will fail - | ||
1072 | * which is the same result anyway i.e. recovery fails. So | ||
1073 | * there is no problem ignoring index requirements and just | ||
1074 | * grabbing a free LEB since we have already established there | ||
1075 | * is not a dirty LEB we could have used instead. | ||
1076 | */ | ||
1077 | if (err == -ENOSPC) { | ||
1078 | dbg_rcvry("could not find a dirty LEB"); | ||
1079 | goto find_free; | ||
1080 | } | ||
1068 | return err; | 1081 | return err; |
1069 | } | 1082 | } |
1070 | ubifs_assert(!(lp.flags & LPROPS_INDEX)); | 1083 | ubifs_assert(!(lp.flags & LPROPS_INDEX)); |
@@ -1139,8 +1152,8 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c) | |||
1139 | find_free: | 1152 | find_free: |
1140 | /* | 1153 | /* |
1141 | * There is no GC head LEB or the free space in the GC head LEB is too | 1154 | * There is no GC head LEB or the free space in the GC head LEB is too |
1142 | * small. Allocate gc_lnum by calling 'ubifs_find_free_leb_for_idx()' so | 1155 | * small, or there are not dirty LEBs. Allocate gc_lnum by calling |
1143 | * GC is not run. | 1156 | * 'ubifs_find_free_leb_for_idx()' so GC is not run. |
1144 | */ | 1157 | */ |
1145 | lnum = ubifs_find_free_leb_for_idx(c); | 1158 | lnum = ubifs_find_free_leb_for_idx(c); |
1146 | if (lnum < 0) { | 1159 | if (lnum < 0) { |
diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c index 02feb59cefca..0b201114a5ad 100644 --- a/fs/ubifs/shrinker.c +++ b/fs/ubifs/shrinker.c | |||
@@ -277,7 +277,7 @@ static int kick_a_thread(void) | |||
277 | return 0; | 277 | return 0; |
278 | } | 278 | } |
279 | 279 | ||
280 | int ubifs_shrinker(int nr, gfp_t gfp_mask) | 280 | int ubifs_shrinker(struct shrinker *shrink, int nr, gfp_t gfp_mask) |
281 | { | 281 | { |
282 | int freed, contention = 0; | 282 | int freed, contention = 0; |
283 | long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt); | 283 | long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt); |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 4d2f2157dd3f..5fc5a0988970 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -1307,6 +1307,8 @@ static int mount_ubifs(struct ubifs_info *c) | |||
1307 | if (err) | 1307 | if (err) |
1308 | goto out_orphans; | 1308 | goto out_orphans; |
1309 | err = ubifs_rcvry_gc_commit(c); | 1309 | err = ubifs_rcvry_gc_commit(c); |
1310 | if (err) | ||
1311 | goto out_orphans; | ||
1310 | } else { | 1312 | } else { |
1311 | err = take_gc_lnum(c); | 1313 | err = take_gc_lnum(c); |
1312 | if (err) | 1314 | if (err) |
@@ -1318,7 +1320,7 @@ static int mount_ubifs(struct ubifs_info *c) | |||
1318 | */ | 1320 | */ |
1319 | err = ubifs_leb_unmap(c, c->gc_lnum); | 1321 | err = ubifs_leb_unmap(c, c->gc_lnum); |
1320 | if (err) | 1322 | if (err) |
1321 | return err; | 1323 | goto out_orphans; |
1322 | } | 1324 | } |
1323 | 1325 | ||
1324 | err = dbg_check_lprops(c); | 1326 | err = dbg_check_lprops(c); |
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 2eef553d50c8..04310878f449 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
@@ -1575,7 +1575,7 @@ int ubifs_tnc_start_commit(struct ubifs_info *c, struct ubifs_zbranch *zroot); | |||
1575 | int ubifs_tnc_end_commit(struct ubifs_info *c); | 1575 | int ubifs_tnc_end_commit(struct ubifs_info *c); |
1576 | 1576 | ||
1577 | /* shrinker.c */ | 1577 | /* shrinker.c */ |
1578 | int ubifs_shrinker(int nr_to_scan, gfp_t gfp_mask); | 1578 | int ubifs_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask); |
1579 | 1579 | ||
1580 | /* commit.c */ | 1580 | /* commit.c */ |
1581 | int ubifs_bg_thread(void *info); | 1581 | int ubifs_bg_thread(void *info); |
diff --git a/fs/udf/file.c b/fs/udf/file.c index 94e06d6bddbd..6e450e01a1bb 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <linux/pagemap.h> | 36 | #include <linux/pagemap.h> |
37 | #include <linux/buffer_head.h> | 37 | #include <linux/buffer_head.h> |
38 | #include <linux/aio.h> | 38 | #include <linux/aio.h> |
39 | #include <linux/smp_lock.h> | ||
40 | 39 | ||
41 | #include "udf_i.h" | 40 | #include "udf_i.h" |
42 | #include "udf_sb.h" | 41 | #include "udf_sb.h" |
diff --git a/fs/udf/super.c b/fs/udf/super.c index 612d1e2e285a..12bb651e5400 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -1579,9 +1579,7 @@ static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh, | |||
1579 | { | 1579 | { |
1580 | struct anchorVolDescPtr *anchor; | 1580 | struct anchorVolDescPtr *anchor; |
1581 | long main_s, main_e, reserve_s, reserve_e; | 1581 | long main_s, main_e, reserve_s, reserve_e; |
1582 | struct udf_sb_info *sbi; | ||
1583 | 1582 | ||
1584 | sbi = UDF_SB(sb); | ||
1585 | anchor = (struct anchorVolDescPtr *)bh->b_data; | 1583 | anchor = (struct anchorVolDescPtr *)bh->b_data; |
1586 | 1584 | ||
1587 | /* Locate the main sequence */ | 1585 | /* Locate the main sequence */ |
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index c8fb13f83b3f..0dce969d6cad 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile | |||
@@ -87,11 +87,9 @@ xfs-y += xfs_alloc.o \ | |||
87 | xfs_trans_buf.o \ | 87 | xfs_trans_buf.o \ |
88 | xfs_trans_extfree.o \ | 88 | xfs_trans_extfree.o \ |
89 | xfs_trans_inode.o \ | 89 | xfs_trans_inode.o \ |
90 | xfs_trans_item.o \ | ||
91 | xfs_utils.o \ | 90 | xfs_utils.o \ |
92 | xfs_vnodeops.o \ | 91 | xfs_vnodeops.o \ |
93 | xfs_rw.o \ | 92 | xfs_rw.o |
94 | xfs_dmops.o | ||
95 | 93 | ||
96 | xfs-$(CONFIG_XFS_TRACE) += xfs_btree_trace.o | 94 | xfs-$(CONFIG_XFS_TRACE) += xfs_btree_trace.o |
97 | 95 | ||
diff --git a/fs/xfs/linux-2.6/xfs_acl.c b/fs/xfs/linux-2.6/xfs_acl.c index 9f769b5b38fc..b2771862fd3d 100644 --- a/fs/xfs/linux-2.6/xfs_acl.c +++ b/fs/xfs/linux-2.6/xfs_acl.c | |||
@@ -225,7 +225,7 @@ xfs_check_acl(struct inode *inode, int mask) | |||
225 | struct posix_acl *acl; | 225 | struct posix_acl *acl; |
226 | int error = -EAGAIN; | 226 | int error = -EAGAIN; |
227 | 227 | ||
228 | xfs_itrace_entry(ip); | 228 | trace_xfs_check_acl(ip); |
229 | 229 | ||
230 | /* | 230 | /* |
231 | * If there is no attribute fork no ACL exists on this inode and | 231 | * If there is no attribute fork no ACL exists on this inode and |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 34640d6dbdcb..d24e78f32f3e 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -21,19 +21,12 @@ | |||
21 | #include "xfs_inum.h" | 21 | #include "xfs_inum.h" |
22 | #include "xfs_sb.h" | 22 | #include "xfs_sb.h" |
23 | #include "xfs_ag.h" | 23 | #include "xfs_ag.h" |
24 | #include "xfs_dir2.h" | ||
25 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
26 | #include "xfs_dmapi.h" | ||
27 | #include "xfs_mount.h" | 25 | #include "xfs_mount.h" |
28 | #include "xfs_bmap_btree.h" | 26 | #include "xfs_bmap_btree.h" |
29 | #include "xfs_alloc_btree.h" | ||
30 | #include "xfs_ialloc_btree.h" | ||
31 | #include "xfs_dir2_sf.h" | ||
32 | #include "xfs_attr_sf.h" | ||
33 | #include "xfs_dinode.h" | 27 | #include "xfs_dinode.h" |
34 | #include "xfs_inode.h" | 28 | #include "xfs_inode.h" |
35 | #include "xfs_alloc.h" | 29 | #include "xfs_alloc.h" |
36 | #include "xfs_btree.h" | ||
37 | #include "xfs_error.h" | 30 | #include "xfs_error.h" |
38 | #include "xfs_rw.h" | 31 | #include "xfs_rw.h" |
39 | #include "xfs_iomap.h" | 32 | #include "xfs_iomap.h" |
@@ -92,18 +85,15 @@ void | |||
92 | xfs_count_page_state( | 85 | xfs_count_page_state( |
93 | struct page *page, | 86 | struct page *page, |
94 | int *delalloc, | 87 | int *delalloc, |
95 | int *unmapped, | ||
96 | int *unwritten) | 88 | int *unwritten) |
97 | { | 89 | { |
98 | struct buffer_head *bh, *head; | 90 | struct buffer_head *bh, *head; |
99 | 91 | ||
100 | *delalloc = *unmapped = *unwritten = 0; | 92 | *delalloc = *unwritten = 0; |
101 | 93 | ||
102 | bh = head = page_buffers(page); | 94 | bh = head = page_buffers(page); |
103 | do { | 95 | do { |
104 | if (buffer_uptodate(bh) && !buffer_mapped(bh)) | 96 | if (buffer_unwritten(bh)) |
105 | (*unmapped) = 1; | ||
106 | else if (buffer_unwritten(bh)) | ||
107 | (*unwritten) = 1; | 97 | (*unwritten) = 1; |
108 | else if (buffer_delay(bh)) | 98 | else if (buffer_delay(bh)) |
109 | (*delalloc) = 1; | 99 | (*delalloc) = 1; |
@@ -212,23 +202,17 @@ xfs_setfilesize( | |||
212 | } | 202 | } |
213 | 203 | ||
214 | /* | 204 | /* |
215 | * Schedule IO completion handling on a xfsdatad if this was | 205 | * Schedule IO completion handling on the final put of an ioend. |
216 | * the final hold on this ioend. If we are asked to wait, | ||
217 | * flush the workqueue. | ||
218 | */ | 206 | */ |
219 | STATIC void | 207 | STATIC void |
220 | xfs_finish_ioend( | 208 | xfs_finish_ioend( |
221 | xfs_ioend_t *ioend, | 209 | struct xfs_ioend *ioend) |
222 | int wait) | ||
223 | { | 210 | { |
224 | if (atomic_dec_and_test(&ioend->io_remaining)) { | 211 | if (atomic_dec_and_test(&ioend->io_remaining)) { |
225 | struct workqueue_struct *wq; | 212 | if (ioend->io_type == IO_UNWRITTEN) |
226 | 213 | queue_work(xfsconvertd_workqueue, &ioend->io_work); | |
227 | wq = (ioend->io_type == IO_UNWRITTEN) ? | 214 | else |
228 | xfsconvertd_workqueue : xfsdatad_workqueue; | 215 | queue_work(xfsdatad_workqueue, &ioend->io_work); |
229 | queue_work(wq, &ioend->io_work); | ||
230 | if (wait) | ||
231 | flush_workqueue(wq); | ||
232 | } | 216 | } |
233 | } | 217 | } |
234 | 218 | ||
@@ -272,11 +256,25 @@ xfs_end_io( | |||
272 | */ | 256 | */ |
273 | if (error == EAGAIN) { | 257 | if (error == EAGAIN) { |
274 | atomic_inc(&ioend->io_remaining); | 258 | atomic_inc(&ioend->io_remaining); |
275 | xfs_finish_ioend(ioend, 0); | 259 | xfs_finish_ioend(ioend); |
276 | /* ensure we don't spin on blocked ioends */ | 260 | /* ensure we don't spin on blocked ioends */ |
277 | delay(1); | 261 | delay(1); |
278 | } else | 262 | } else { |
263 | if (ioend->io_iocb) | ||
264 | aio_complete(ioend->io_iocb, ioend->io_result, 0); | ||
279 | xfs_destroy_ioend(ioend); | 265 | xfs_destroy_ioend(ioend); |
266 | } | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * Call IO completion handling in caller context on the final put of an ioend. | ||
271 | */ | ||
272 | STATIC void | ||
273 | xfs_finish_ioend_sync( | ||
274 | struct xfs_ioend *ioend) | ||
275 | { | ||
276 | if (atomic_dec_and_test(&ioend->io_remaining)) | ||
277 | xfs_end_io(&ioend->io_work); | ||
280 | } | 278 | } |
281 | 279 | ||
282 | /* | 280 | /* |
@@ -309,6 +307,8 @@ xfs_alloc_ioend( | |||
309 | atomic_inc(&XFS_I(ioend->io_inode)->i_iocount); | 307 | atomic_inc(&XFS_I(ioend->io_inode)->i_iocount); |
310 | ioend->io_offset = 0; | 308 | ioend->io_offset = 0; |
311 | ioend->io_size = 0; | 309 | ioend->io_size = 0; |
310 | ioend->io_iocb = NULL; | ||
311 | ioend->io_result = 0; | ||
312 | 312 | ||
313 | INIT_WORK(&ioend->io_work, xfs_end_io); | 313 | INIT_WORK(&ioend->io_work, xfs_end_io); |
314 | return ioend; | 314 | return ioend; |
@@ -358,7 +358,7 @@ xfs_end_bio( | |||
358 | bio->bi_end_io = NULL; | 358 | bio->bi_end_io = NULL; |
359 | bio_put(bio); | 359 | bio_put(bio); |
360 | 360 | ||
361 | xfs_finish_ioend(ioend, 0); | 361 | xfs_finish_ioend(ioend); |
362 | } | 362 | } |
363 | 363 | ||
364 | STATIC void | 364 | STATIC void |
@@ -500,7 +500,7 @@ xfs_submit_ioend( | |||
500 | } | 500 | } |
501 | if (bio) | 501 | if (bio) |
502 | xfs_submit_ioend_bio(wbc, ioend, bio); | 502 | xfs_submit_ioend_bio(wbc, ioend, bio); |
503 | xfs_finish_ioend(ioend, 0); | 503 | xfs_finish_ioend(ioend); |
504 | } while ((ioend = next) != NULL); | 504 | } while ((ioend = next) != NULL); |
505 | } | 505 | } |
506 | 506 | ||
@@ -614,31 +614,30 @@ xfs_map_at_offset( | |||
614 | STATIC unsigned int | 614 | STATIC unsigned int |
615 | xfs_probe_page( | 615 | xfs_probe_page( |
616 | struct page *page, | 616 | struct page *page, |
617 | unsigned int pg_offset, | 617 | unsigned int pg_offset) |
618 | int mapped) | ||
619 | { | 618 | { |
619 | struct buffer_head *bh, *head; | ||
620 | int ret = 0; | 620 | int ret = 0; |
621 | 621 | ||
622 | if (PageWriteback(page)) | 622 | if (PageWriteback(page)) |
623 | return 0; | 623 | return 0; |
624 | if (!PageDirty(page)) | ||
625 | return 0; | ||
626 | if (!page->mapping) | ||
627 | return 0; | ||
628 | if (!page_has_buffers(page)) | ||
629 | return 0; | ||
624 | 630 | ||
625 | if (page->mapping && PageDirty(page)) { | 631 | bh = head = page_buffers(page); |
626 | if (page_has_buffers(page)) { | 632 | do { |
627 | struct buffer_head *bh, *head; | 633 | if (!buffer_uptodate(bh)) |
628 | 634 | break; | |
629 | bh = head = page_buffers(page); | 635 | if (!buffer_mapped(bh)) |
630 | do { | 636 | break; |
631 | if (!buffer_uptodate(bh)) | 637 | ret += bh->b_size; |
632 | break; | 638 | if (ret >= pg_offset) |
633 | if (mapped != buffer_mapped(bh)) | 639 | break; |
634 | break; | 640 | } while ((bh = bh->b_this_page) != head); |
635 | ret += bh->b_size; | ||
636 | if (ret >= pg_offset) | ||
637 | break; | ||
638 | } while ((bh = bh->b_this_page) != head); | ||
639 | } else | ||
640 | ret = mapped ? 0 : PAGE_CACHE_SIZE; | ||
641 | } | ||
642 | 641 | ||
643 | return ret; | 642 | return ret; |
644 | } | 643 | } |
@@ -648,8 +647,7 @@ xfs_probe_cluster( | |||
648 | struct inode *inode, | 647 | struct inode *inode, |
649 | struct page *startpage, | 648 | struct page *startpage, |
650 | struct buffer_head *bh, | 649 | struct buffer_head *bh, |
651 | struct buffer_head *head, | 650 | struct buffer_head *head) |
652 | int mapped) | ||
653 | { | 651 | { |
654 | struct pagevec pvec; | 652 | struct pagevec pvec; |
655 | pgoff_t tindex, tlast, tloff; | 653 | pgoff_t tindex, tlast, tloff; |
@@ -658,7 +656,7 @@ xfs_probe_cluster( | |||
658 | 656 | ||
659 | /* First sum forwards in this page */ | 657 | /* First sum forwards in this page */ |
660 | do { | 658 | do { |
661 | if (!buffer_uptodate(bh) || (mapped != buffer_mapped(bh))) | 659 | if (!buffer_uptodate(bh) || !buffer_mapped(bh)) |
662 | return total; | 660 | return total; |
663 | total += bh->b_size; | 661 | total += bh->b_size; |
664 | } while ((bh = bh->b_this_page) != head); | 662 | } while ((bh = bh->b_this_page) != head); |
@@ -692,7 +690,7 @@ xfs_probe_cluster( | |||
692 | pg_offset = PAGE_CACHE_SIZE; | 690 | pg_offset = PAGE_CACHE_SIZE; |
693 | 691 | ||
694 | if (page->index == tindex && trylock_page(page)) { | 692 | if (page->index == tindex && trylock_page(page)) { |
695 | pg_len = xfs_probe_page(page, pg_offset, mapped); | 693 | pg_len = xfs_probe_page(page, pg_offset); |
696 | unlock_page(page); | 694 | unlock_page(page); |
697 | } | 695 | } |
698 | 696 | ||
@@ -761,7 +759,6 @@ xfs_convert_page( | |||
761 | struct xfs_bmbt_irec *imap, | 759 | struct xfs_bmbt_irec *imap, |
762 | xfs_ioend_t **ioendp, | 760 | xfs_ioend_t **ioendp, |
763 | struct writeback_control *wbc, | 761 | struct writeback_control *wbc, |
764 | int startio, | ||
765 | int all_bh) | 762 | int all_bh) |
766 | { | 763 | { |
767 | struct buffer_head *bh, *head; | 764 | struct buffer_head *bh, *head; |
@@ -832,19 +829,14 @@ xfs_convert_page( | |||
832 | ASSERT(imap->br_startblock != DELAYSTARTBLOCK); | 829 | ASSERT(imap->br_startblock != DELAYSTARTBLOCK); |
833 | 830 | ||
834 | xfs_map_at_offset(inode, bh, imap, offset); | 831 | xfs_map_at_offset(inode, bh, imap, offset); |
835 | if (startio) { | 832 | xfs_add_to_ioend(inode, bh, offset, type, |
836 | xfs_add_to_ioend(inode, bh, offset, | 833 | ioendp, done); |
837 | type, ioendp, done); | 834 | |
838 | } else { | ||
839 | set_buffer_dirty(bh); | ||
840 | unlock_buffer(bh); | ||
841 | mark_buffer_dirty(bh); | ||
842 | } | ||
843 | page_dirty--; | 835 | page_dirty--; |
844 | count++; | 836 | count++; |
845 | } else { | 837 | } else { |
846 | type = IO_NEW; | 838 | type = IO_NEW; |
847 | if (buffer_mapped(bh) && all_bh && startio) { | 839 | if (buffer_mapped(bh) && all_bh) { |
848 | lock_buffer(bh); | 840 | lock_buffer(bh); |
849 | xfs_add_to_ioend(inode, bh, offset, | 841 | xfs_add_to_ioend(inode, bh, offset, |
850 | type, ioendp, done); | 842 | type, ioendp, done); |
@@ -859,14 +851,12 @@ xfs_convert_page( | |||
859 | if (uptodate && bh == head) | 851 | if (uptodate && bh == head) |
860 | SetPageUptodate(page); | 852 | SetPageUptodate(page); |
861 | 853 | ||
862 | if (startio) { | 854 | if (count) { |
863 | if (count) { | 855 | wbc->nr_to_write--; |
864 | wbc->nr_to_write--; | 856 | if (wbc->nr_to_write <= 0) |
865 | if (wbc->nr_to_write <= 0) | 857 | done = 1; |
866 | done = 1; | ||
867 | } | ||
868 | xfs_start_page_writeback(page, !page_dirty, count); | ||
869 | } | 858 | } |
859 | xfs_start_page_writeback(page, !page_dirty, count); | ||
870 | 860 | ||
871 | return done; | 861 | return done; |
872 | fail_unlock_page: | 862 | fail_unlock_page: |
@@ -886,7 +876,6 @@ xfs_cluster_write( | |||
886 | struct xfs_bmbt_irec *imap, | 876 | struct xfs_bmbt_irec *imap, |
887 | xfs_ioend_t **ioendp, | 877 | xfs_ioend_t **ioendp, |
888 | struct writeback_control *wbc, | 878 | struct writeback_control *wbc, |
889 | int startio, | ||
890 | int all_bh, | 879 | int all_bh, |
891 | pgoff_t tlast) | 880 | pgoff_t tlast) |
892 | { | 881 | { |
@@ -902,7 +891,7 @@ xfs_cluster_write( | |||
902 | 891 | ||
903 | for (i = 0; i < pagevec_count(&pvec); i++) { | 892 | for (i = 0; i < pagevec_count(&pvec); i++) { |
904 | done = xfs_convert_page(inode, pvec.pages[i], tindex++, | 893 | done = xfs_convert_page(inode, pvec.pages[i], tindex++, |
905 | imap, ioendp, wbc, startio, all_bh); | 894 | imap, ioendp, wbc, all_bh); |
906 | if (done) | 895 | if (done) |
907 | break; | 896 | break; |
908 | } | 897 | } |
@@ -981,7 +970,7 @@ xfs_aops_discard_page( | |||
981 | */ | 970 | */ |
982 | error = xfs_bmapi(NULL, ip, offset_fsb, 1, | 971 | error = xfs_bmapi(NULL, ip, offset_fsb, 1, |
983 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, | 972 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, |
984 | &nimaps, NULL, NULL); | 973 | &nimaps, NULL); |
985 | 974 | ||
986 | if (error) { | 975 | if (error) { |
987 | /* something screwed, just bail */ | 976 | /* something screwed, just bail */ |
@@ -1009,7 +998,7 @@ xfs_aops_discard_page( | |||
1009 | */ | 998 | */ |
1010 | xfs_bmap_init(&flist, &firstblock); | 999 | xfs_bmap_init(&flist, &firstblock); |
1011 | error = xfs_bunmapi(NULL, ip, offset_fsb, 1, 0, 1, &firstblock, | 1000 | error = xfs_bunmapi(NULL, ip, offset_fsb, 1, 0, 1, &firstblock, |
1012 | &flist, NULL, &done); | 1001 | &flist, &done); |
1013 | 1002 | ||
1014 | ASSERT(!flist.xbf_count && !flist.xbf_first); | 1003 | ASSERT(!flist.xbf_count && !flist.xbf_first); |
1015 | if (error) { | 1004 | if (error) { |
@@ -1032,50 +1021,66 @@ out_invalidate: | |||
1032 | } | 1021 | } |
1033 | 1022 | ||
1034 | /* | 1023 | /* |
1035 | * Calling this without startio set means we are being asked to make a dirty | 1024 | * Write out a dirty page. |
1036 | * page ready for freeing it's buffers. When called with startio set then | 1025 | * |
1037 | * we are coming from writepage. | 1026 | * For delalloc space on the page we need to allocate space and flush it. |
1027 | * For unwritten space on the page we need to start the conversion to | ||
1028 | * regular allocated space. | ||
1029 | * For any other dirty buffer heads on the page we should flush them. | ||
1038 | * | 1030 | * |
1039 | * When called with startio set it is important that we write the WHOLE | 1031 | * If we detect that a transaction would be required to flush the page, we |
1040 | * page if possible. | 1032 | * have to check the process flags first, if we are already in a transaction |
1041 | * The bh->b_state's cannot know if any of the blocks or which block for | 1033 | * or disk I/O during allocations is off, we need to fail the writepage and |
1042 | * that matter are dirty due to mmap writes, and therefore bh uptodate is | 1034 | * redirty the page. |
1043 | * only valid if the page itself isn't completely uptodate. Some layers | ||
1044 | * may clear the page dirty flag prior to calling write page, under the | ||
1045 | * assumption the entire page will be written out; by not writing out the | ||
1046 | * whole page the page can be reused before all valid dirty data is | ||
1047 | * written out. Note: in the case of a page that has been dirty'd by | ||
1048 | * mapwrite and but partially setup by block_prepare_write the | ||
1049 | * bh->b_states's will not agree and only ones setup by BPW/BCW will have | ||
1050 | * valid state, thus the whole page must be written out thing. | ||
1051 | */ | 1035 | */ |
1052 | |||
1053 | STATIC int | 1036 | STATIC int |
1054 | xfs_page_state_convert( | 1037 | xfs_vm_writepage( |
1055 | struct inode *inode, | 1038 | struct page *page, |
1056 | struct page *page, | 1039 | struct writeback_control *wbc) |
1057 | struct writeback_control *wbc, | ||
1058 | int startio, | ||
1059 | int unmapped) /* also implies page uptodate */ | ||
1060 | { | 1040 | { |
1041 | struct inode *inode = page->mapping->host; | ||
1042 | int delalloc, unwritten; | ||
1061 | struct buffer_head *bh, *head; | 1043 | struct buffer_head *bh, *head; |
1062 | struct xfs_bmbt_irec imap; | 1044 | struct xfs_bmbt_irec imap; |
1063 | xfs_ioend_t *ioend = NULL, *iohead = NULL; | 1045 | xfs_ioend_t *ioend = NULL, *iohead = NULL; |
1064 | loff_t offset; | 1046 | loff_t offset; |
1065 | unsigned long p_offset = 0; | ||
1066 | unsigned int type; | 1047 | unsigned int type; |
1067 | __uint64_t end_offset; | 1048 | __uint64_t end_offset; |
1068 | pgoff_t end_index, last_index; | 1049 | pgoff_t end_index, last_index; |
1069 | ssize_t size, len; | 1050 | ssize_t size, len; |
1070 | int flags, err, imap_valid = 0, uptodate = 1; | 1051 | int flags, err, imap_valid = 0, uptodate = 1; |
1071 | int page_dirty, count = 0; | 1052 | int count = 0; |
1072 | int trylock = 0; | 1053 | int all_bh = 0; |
1073 | int all_bh = unmapped; | ||
1074 | 1054 | ||
1075 | if (startio) { | 1055 | trace_xfs_writepage(inode, page, 0); |
1076 | if (wbc->sync_mode == WB_SYNC_NONE && wbc->nonblocking) | 1056 | |
1077 | trylock |= BMAPI_TRYLOCK; | 1057 | ASSERT(page_has_buffers(page)); |
1078 | } | 1058 | |
1059 | /* | ||
1060 | * Refuse to write the page out if we are called from reclaim context. | ||
1061 | * | ||
1062 | * This avoids stack overflows when called from deeply used stacks in | ||
1063 | * random callers for direct reclaim or memcg reclaim. We explicitly | ||
1064 | * allow reclaim from kswapd as the stack usage there is relatively low. | ||
1065 | * | ||
1066 | * This should really be done by the core VM, but until that happens | ||
1067 | * filesystems like XFS, btrfs and ext4 have to take care of this | ||
1068 | * by themselves. | ||
1069 | */ | ||
1070 | if ((current->flags & (PF_MEMALLOC|PF_KSWAPD)) == PF_MEMALLOC) | ||
1071 | goto out_fail; | ||
1072 | |||
1073 | /* | ||
1074 | * We need a transaction if there are delalloc or unwritten buffers | ||
1075 | * on the page. | ||
1076 | * | ||
1077 | * If we need a transaction and the process flags say we are already | ||
1078 | * in a transaction, or no IO is allowed then mark the page dirty | ||
1079 | * again and leave the page as is. | ||
1080 | */ | ||
1081 | xfs_count_page_state(page, &delalloc, &unwritten); | ||
1082 | if ((current->flags & PF_FSTRANS) && (delalloc || unwritten)) | ||
1083 | goto out_fail; | ||
1079 | 1084 | ||
1080 | /* Is this page beyond the end of the file? */ | 1085 | /* Is this page beyond the end of the file? */ |
1081 | offset = i_size_read(inode); | 1086 | offset = i_size_read(inode); |
@@ -1084,50 +1089,33 @@ xfs_page_state_convert( | |||
1084 | if (page->index >= end_index) { | 1089 | if (page->index >= end_index) { |
1085 | if ((page->index >= end_index + 1) || | 1090 | if ((page->index >= end_index + 1) || |
1086 | !(i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) { | 1091 | !(i_size_read(inode) & (PAGE_CACHE_SIZE - 1))) { |
1087 | if (startio) | 1092 | unlock_page(page); |
1088 | unlock_page(page); | ||
1089 | return 0; | 1093 | return 0; |
1090 | } | 1094 | } |
1091 | } | 1095 | } |
1092 | 1096 | ||
1093 | /* | ||
1094 | * page_dirty is initially a count of buffers on the page before | ||
1095 | * EOF and is decremented as we move each into a cleanable state. | ||
1096 | * | ||
1097 | * Derivation: | ||
1098 | * | ||
1099 | * End offset is the highest offset that this page should represent. | ||
1100 | * If we are on the last page, (end_offset & (PAGE_CACHE_SIZE - 1)) | ||
1101 | * will evaluate non-zero and be less than PAGE_CACHE_SIZE and | ||
1102 | * hence give us the correct page_dirty count. On any other page, | ||
1103 | * it will be zero and in that case we need page_dirty to be the | ||
1104 | * count of buffers on the page. | ||
1105 | */ | ||
1106 | end_offset = min_t(unsigned long long, | 1097 | end_offset = min_t(unsigned long long, |
1107 | (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset); | 1098 | (xfs_off_t)(page->index + 1) << PAGE_CACHE_SHIFT, |
1099 | offset); | ||
1108 | len = 1 << inode->i_blkbits; | 1100 | len = 1 << inode->i_blkbits; |
1109 | p_offset = min_t(unsigned long, end_offset & (PAGE_CACHE_SIZE - 1), | ||
1110 | PAGE_CACHE_SIZE); | ||
1111 | p_offset = p_offset ? roundup(p_offset, len) : PAGE_CACHE_SIZE; | ||
1112 | page_dirty = p_offset / len; | ||
1113 | 1101 | ||
1114 | bh = head = page_buffers(page); | 1102 | bh = head = page_buffers(page); |
1115 | offset = page_offset(page); | 1103 | offset = page_offset(page); |
1116 | flags = BMAPI_READ; | 1104 | flags = BMAPI_READ; |
1117 | type = IO_NEW; | 1105 | type = IO_NEW; |
1118 | 1106 | ||
1119 | /* TODO: cleanup count and page_dirty */ | ||
1120 | |||
1121 | do { | 1107 | do { |
1122 | if (offset >= end_offset) | 1108 | if (offset >= end_offset) |
1123 | break; | 1109 | break; |
1124 | if (!buffer_uptodate(bh)) | 1110 | if (!buffer_uptodate(bh)) |
1125 | uptodate = 0; | 1111 | uptodate = 0; |
1126 | if (!(PageUptodate(page) || buffer_uptodate(bh)) && !startio) { | 1112 | |
1127 | /* | 1113 | /* |
1128 | * the iomap is actually still valid, but the ioend | 1114 | * A hole may still be marked uptodate because discard_buffer |
1129 | * isn't. shouldn't happen too often. | 1115 | * leaves the flag set. |
1130 | */ | 1116 | */ |
1117 | if (!buffer_mapped(bh) && buffer_uptodate(bh)) { | ||
1118 | ASSERT(!buffer_dirty(bh)); | ||
1131 | imap_valid = 0; | 1119 | imap_valid = 0; |
1132 | continue; | 1120 | continue; |
1133 | } | 1121 | } |
@@ -1135,19 +1123,7 @@ xfs_page_state_convert( | |||
1135 | if (imap_valid) | 1123 | if (imap_valid) |
1136 | imap_valid = xfs_imap_valid(inode, &imap, offset); | 1124 | imap_valid = xfs_imap_valid(inode, &imap, offset); |
1137 | 1125 | ||
1138 | /* | 1126 | if (buffer_unwritten(bh) || buffer_delay(bh)) { |
1139 | * First case, map an unwritten extent and prepare for | ||
1140 | * extent state conversion transaction on completion. | ||
1141 | * | ||
1142 | * Second case, allocate space for a delalloc buffer. | ||
1143 | * We can return EAGAIN here in the release page case. | ||
1144 | * | ||
1145 | * Third case, an unmapped buffer was found, and we are | ||
1146 | * in a path where we need to write the whole page out. | ||
1147 | */ | ||
1148 | if (buffer_unwritten(bh) || buffer_delay(bh) || | ||
1149 | ((buffer_uptodate(bh) || PageUptodate(page)) && | ||
1150 | !buffer_mapped(bh) && (unmapped || startio))) { | ||
1151 | int new_ioend = 0; | 1127 | int new_ioend = 0; |
1152 | 1128 | ||
1153 | /* | 1129 | /* |
@@ -1161,15 +1137,16 @@ xfs_page_state_convert( | |||
1161 | flags = BMAPI_WRITE | BMAPI_IGNSTATE; | 1137 | flags = BMAPI_WRITE | BMAPI_IGNSTATE; |
1162 | } else if (buffer_delay(bh)) { | 1138 | } else if (buffer_delay(bh)) { |
1163 | type = IO_DELAY; | 1139 | type = IO_DELAY; |
1164 | flags = BMAPI_ALLOCATE | trylock; | 1140 | flags = BMAPI_ALLOCATE; |
1165 | } else { | 1141 | |
1166 | type = IO_NEW; | 1142 | if (wbc->sync_mode == WB_SYNC_NONE && |
1167 | flags = BMAPI_WRITE | BMAPI_MMAP; | 1143 | wbc->nonblocking) |
1144 | flags |= BMAPI_TRYLOCK; | ||
1168 | } | 1145 | } |
1169 | 1146 | ||
1170 | if (!imap_valid) { | 1147 | if (!imap_valid) { |
1171 | /* | 1148 | /* |
1172 | * if we didn't have a valid mapping then we | 1149 | * If we didn't have a valid mapping then we |
1173 | * need to ensure that we put the new mapping | 1150 | * need to ensure that we put the new mapping |
1174 | * in a new ioend structure. This needs to be | 1151 | * in a new ioend structure. This needs to be |
1175 | * done to ensure that the ioends correctly | 1152 | * done to ensure that the ioends correctly |
@@ -1177,14 +1154,7 @@ xfs_page_state_convert( | |||
1177 | * for unwritten extent conversion. | 1154 | * for unwritten extent conversion. |
1178 | */ | 1155 | */ |
1179 | new_ioend = 1; | 1156 | new_ioend = 1; |
1180 | if (type == IO_NEW) { | 1157 | err = xfs_map_blocks(inode, offset, len, |
1181 | size = xfs_probe_cluster(inode, | ||
1182 | page, bh, head, 0); | ||
1183 | } else { | ||
1184 | size = len; | ||
1185 | } | ||
1186 | |||
1187 | err = xfs_map_blocks(inode, offset, size, | ||
1188 | &imap, flags); | 1158 | &imap, flags); |
1189 | if (err) | 1159 | if (err) |
1190 | goto error; | 1160 | goto error; |
@@ -1193,19 +1163,11 @@ xfs_page_state_convert( | |||
1193 | } | 1163 | } |
1194 | if (imap_valid) { | 1164 | if (imap_valid) { |
1195 | xfs_map_at_offset(inode, bh, &imap, offset); | 1165 | xfs_map_at_offset(inode, bh, &imap, offset); |
1196 | if (startio) { | 1166 | xfs_add_to_ioend(inode, bh, offset, type, |
1197 | xfs_add_to_ioend(inode, bh, offset, | 1167 | &ioend, new_ioend); |
1198 | type, &ioend, | ||
1199 | new_ioend); | ||
1200 | } else { | ||
1201 | set_buffer_dirty(bh); | ||
1202 | unlock_buffer(bh); | ||
1203 | mark_buffer_dirty(bh); | ||
1204 | } | ||
1205 | page_dirty--; | ||
1206 | count++; | 1168 | count++; |
1207 | } | 1169 | } |
1208 | } else if (buffer_uptodate(bh) && startio) { | 1170 | } else if (buffer_uptodate(bh)) { |
1209 | /* | 1171 | /* |
1210 | * we got here because the buffer is already mapped. | 1172 | * we got here because the buffer is already mapped. |
1211 | * That means it must already have extents allocated | 1173 | * That means it must already have extents allocated |
@@ -1213,8 +1175,7 @@ xfs_page_state_convert( | |||
1213 | */ | 1175 | */ |
1214 | if (!imap_valid || flags != BMAPI_READ) { | 1176 | if (!imap_valid || flags != BMAPI_READ) { |
1215 | flags = BMAPI_READ; | 1177 | flags = BMAPI_READ; |
1216 | size = xfs_probe_cluster(inode, page, bh, | 1178 | size = xfs_probe_cluster(inode, page, bh, head); |
1217 | head, 1); | ||
1218 | err = xfs_map_blocks(inode, offset, size, | 1179 | err = xfs_map_blocks(inode, offset, size, |
1219 | &imap, flags); | 1180 | &imap, flags); |
1220 | if (err) | 1181 | if (err) |
@@ -1233,18 +1194,16 @@ xfs_page_state_convert( | |||
1233 | */ | 1194 | */ |
1234 | type = IO_NEW; | 1195 | type = IO_NEW; |
1235 | if (trylock_buffer(bh)) { | 1196 | if (trylock_buffer(bh)) { |
1236 | ASSERT(buffer_mapped(bh)); | ||
1237 | if (imap_valid) | 1197 | if (imap_valid) |
1238 | all_bh = 1; | 1198 | all_bh = 1; |
1239 | xfs_add_to_ioend(inode, bh, offset, type, | 1199 | xfs_add_to_ioend(inode, bh, offset, type, |
1240 | &ioend, !imap_valid); | 1200 | &ioend, !imap_valid); |
1241 | page_dirty--; | ||
1242 | count++; | 1201 | count++; |
1243 | } else { | 1202 | } else { |
1244 | imap_valid = 0; | 1203 | imap_valid = 0; |
1245 | } | 1204 | } |
1246 | } else if ((buffer_uptodate(bh) || PageUptodate(page)) && | 1205 | } else if (PageUptodate(page)) { |
1247 | (unmapped || startio)) { | 1206 | ASSERT(buffer_mapped(bh)); |
1248 | imap_valid = 0; | 1207 | imap_valid = 0; |
1249 | } | 1208 | } |
1250 | 1209 | ||
@@ -1256,8 +1215,7 @@ xfs_page_state_convert( | |||
1256 | if (uptodate && bh == head) | 1215 | if (uptodate && bh == head) |
1257 | SetPageUptodate(page); | 1216 | SetPageUptodate(page); |
1258 | 1217 | ||
1259 | if (startio) | 1218 | xfs_start_page_writeback(page, 1, count); |
1260 | xfs_start_page_writeback(page, 1, count); | ||
1261 | 1219 | ||
1262 | if (ioend && imap_valid) { | 1220 | if (ioend && imap_valid) { |
1263 | xfs_off_t end_index; | 1221 | xfs_off_t end_index; |
@@ -1275,131 +1233,27 @@ xfs_page_state_convert( | |||
1275 | end_index = last_index; | 1233 | end_index = last_index; |
1276 | 1234 | ||
1277 | xfs_cluster_write(inode, page->index + 1, &imap, &ioend, | 1235 | xfs_cluster_write(inode, page->index + 1, &imap, &ioend, |
1278 | wbc, startio, all_bh, end_index); | 1236 | wbc, all_bh, end_index); |
1279 | } | 1237 | } |
1280 | 1238 | ||
1281 | if (iohead) | 1239 | if (iohead) |
1282 | xfs_submit_ioend(wbc, iohead); | 1240 | xfs_submit_ioend(wbc, iohead); |
1283 | 1241 | ||
1284 | return page_dirty; | 1242 | return 0; |
1285 | 1243 | ||
1286 | error: | 1244 | error: |
1287 | if (iohead) | 1245 | if (iohead) |
1288 | xfs_cancel_ioend(iohead); | 1246 | xfs_cancel_ioend(iohead); |
1289 | 1247 | ||
1290 | /* | 1248 | xfs_aops_discard_page(page); |
1291 | * If it's delalloc and we have nowhere to put it, | 1249 | ClearPageUptodate(page); |
1292 | * throw it away, unless the lower layers told | 1250 | unlock_page(page); |
1293 | * us to try again. | ||
1294 | */ | ||
1295 | if (err != -EAGAIN) { | ||
1296 | if (!unmapped) | ||
1297 | xfs_aops_discard_page(page); | ||
1298 | ClearPageUptodate(page); | ||
1299 | } | ||
1300 | return err; | 1251 | return err; |
1301 | } | ||
1302 | |||
1303 | /* | ||
1304 | * writepage: Called from one of two places: | ||
1305 | * | ||
1306 | * 1. we are flushing a delalloc buffer head. | ||
1307 | * | ||
1308 | * 2. we are writing out a dirty page. Typically the page dirty | ||
1309 | * state is cleared before we get here. In this case is it | ||
1310 | * conceivable we have no buffer heads. | ||
1311 | * | ||
1312 | * For delalloc space on the page we need to allocate space and | ||
1313 | * flush it. For unmapped buffer heads on the page we should | ||
1314 | * allocate space if the page is uptodate. For any other dirty | ||
1315 | * buffer heads on the page we should flush them. | ||
1316 | * | ||
1317 | * If we detect that a transaction would be required to flush | ||
1318 | * the page, we have to check the process flags first, if we | ||
1319 | * are already in a transaction or disk I/O during allocations | ||
1320 | * is off, we need to fail the writepage and redirty the page. | ||
1321 | */ | ||
1322 | |||
1323 | STATIC int | ||
1324 | xfs_vm_writepage( | ||
1325 | struct page *page, | ||
1326 | struct writeback_control *wbc) | ||
1327 | { | ||
1328 | int error; | ||
1329 | int need_trans; | ||
1330 | int delalloc, unmapped, unwritten; | ||
1331 | struct inode *inode = page->mapping->host; | ||
1332 | |||
1333 | trace_xfs_writepage(inode, page, 0); | ||
1334 | |||
1335 | /* | ||
1336 | * Refuse to write the page out if we are called from reclaim context. | ||
1337 | * | ||
1338 | * This is primarily to avoid stack overflows when called from deep | ||
1339 | * used stacks in random callers for direct reclaim, but disabling | ||
1340 | * reclaim for kswap is a nice side-effect as kswapd causes rather | ||
1341 | * suboptimal I/O patters, too. | ||
1342 | * | ||
1343 | * This should really be done by the core VM, but until that happens | ||
1344 | * filesystems like XFS, btrfs and ext4 have to take care of this | ||
1345 | * by themselves. | ||
1346 | */ | ||
1347 | if (current->flags & PF_MEMALLOC) | ||
1348 | goto out_fail; | ||
1349 | |||
1350 | /* | ||
1351 | * We need a transaction if: | ||
1352 | * 1. There are delalloc buffers on the page | ||
1353 | * 2. The page is uptodate and we have unmapped buffers | ||
1354 | * 3. The page is uptodate and we have no buffers | ||
1355 | * 4. There are unwritten buffers on the page | ||
1356 | */ | ||
1357 | |||
1358 | if (!page_has_buffers(page)) { | ||
1359 | unmapped = 1; | ||
1360 | need_trans = 1; | ||
1361 | } else { | ||
1362 | xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); | ||
1363 | if (!PageUptodate(page)) | ||
1364 | unmapped = 0; | ||
1365 | need_trans = delalloc + unmapped + unwritten; | ||
1366 | } | ||
1367 | |||
1368 | /* | ||
1369 | * If we need a transaction and the process flags say | ||
1370 | * we are already in a transaction, or no IO is allowed | ||
1371 | * then mark the page dirty again and leave the page | ||
1372 | * as is. | ||
1373 | */ | ||
1374 | if (current_test_flags(PF_FSTRANS) && need_trans) | ||
1375 | goto out_fail; | ||
1376 | |||
1377 | /* | ||
1378 | * Delay hooking up buffer heads until we have | ||
1379 | * made our go/no-go decision. | ||
1380 | */ | ||
1381 | if (!page_has_buffers(page)) | ||
1382 | create_empty_buffers(page, 1 << inode->i_blkbits, 0); | ||
1383 | |||
1384 | /* | ||
1385 | * Convert delayed allocate, unwritten or unmapped space | ||
1386 | * to real space and flush out to disk. | ||
1387 | */ | ||
1388 | error = xfs_page_state_convert(inode, page, wbc, 1, unmapped); | ||
1389 | if (error == -EAGAIN) | ||
1390 | goto out_fail; | ||
1391 | if (unlikely(error < 0)) | ||
1392 | goto out_unlock; | ||
1393 | |||
1394 | return 0; | ||
1395 | 1252 | ||
1396 | out_fail: | 1253 | out_fail: |
1397 | redirty_page_for_writepage(wbc, page); | 1254 | redirty_page_for_writepage(wbc, page); |
1398 | unlock_page(page); | 1255 | unlock_page(page); |
1399 | return 0; | 1256 | return 0; |
1400 | out_unlock: | ||
1401 | unlock_page(page); | ||
1402 | return error; | ||
1403 | } | 1257 | } |
1404 | 1258 | ||
1405 | STATIC int | 1259 | STATIC int |
@@ -1413,65 +1267,27 @@ xfs_vm_writepages( | |||
1413 | 1267 | ||
1414 | /* | 1268 | /* |
1415 | * Called to move a page into cleanable state - and from there | 1269 | * Called to move a page into cleanable state - and from there |
1416 | * to be released. Possibly the page is already clean. We always | 1270 | * to be released. The page should already be clean. We always |
1417 | * have buffer heads in this call. | 1271 | * have buffer heads in this call. |
1418 | * | 1272 | * |
1419 | * Returns 0 if the page is ok to release, 1 otherwise. | 1273 | * Returns 1 if the page is ok to release, 0 otherwise. |
1420 | * | ||
1421 | * Possible scenarios are: | ||
1422 | * | ||
1423 | * 1. We are being called to release a page which has been written | ||
1424 | * to via regular I/O. buffer heads will be dirty and possibly | ||
1425 | * delalloc. If no delalloc buffer heads in this case then we | ||
1426 | * can just return zero. | ||
1427 | * | ||
1428 | * 2. We are called to release a page which has been written via | ||
1429 | * mmap, all we need to do is ensure there is no delalloc | ||
1430 | * state in the buffer heads, if not we can let the caller | ||
1431 | * free them and we should come back later via writepage. | ||
1432 | */ | 1274 | */ |
1433 | STATIC int | 1275 | STATIC int |
1434 | xfs_vm_releasepage( | 1276 | xfs_vm_releasepage( |
1435 | struct page *page, | 1277 | struct page *page, |
1436 | gfp_t gfp_mask) | 1278 | gfp_t gfp_mask) |
1437 | { | 1279 | { |
1438 | struct inode *inode = page->mapping->host; | 1280 | int delalloc, unwritten; |
1439 | int dirty, delalloc, unmapped, unwritten; | ||
1440 | struct writeback_control wbc = { | ||
1441 | .sync_mode = WB_SYNC_ALL, | ||
1442 | .nr_to_write = 1, | ||
1443 | }; | ||
1444 | 1281 | ||
1445 | trace_xfs_releasepage(inode, page, 0); | 1282 | trace_xfs_releasepage(page->mapping->host, page, 0); |
1446 | |||
1447 | if (!page_has_buffers(page)) | ||
1448 | return 0; | ||
1449 | 1283 | ||
1450 | xfs_count_page_state(page, &delalloc, &unmapped, &unwritten); | 1284 | xfs_count_page_state(page, &delalloc, &unwritten); |
1451 | if (!delalloc && !unwritten) | ||
1452 | goto free_buffers; | ||
1453 | 1285 | ||
1454 | if (!(gfp_mask & __GFP_FS)) | 1286 | if (WARN_ON(delalloc)) |
1455 | return 0; | 1287 | return 0; |
1456 | 1288 | if (WARN_ON(unwritten)) | |
1457 | /* If we are already inside a transaction or the thread cannot | ||
1458 | * do I/O, we cannot release this page. | ||
1459 | */ | ||
1460 | if (current_test_flags(PF_FSTRANS)) | ||
1461 | return 0; | 1289 | return 0; |
1462 | 1290 | ||
1463 | /* | ||
1464 | * Convert delalloc space to real space, do not flush the | ||
1465 | * data out to disk, that will be done by the caller. | ||
1466 | * Never need to allocate space here - we will always | ||
1467 | * come back to writepage in that case. | ||
1468 | */ | ||
1469 | dirty = xfs_page_state_convert(inode, page, &wbc, 0, 0); | ||
1470 | if (dirty == 0 && !unwritten) | ||
1471 | goto free_buffers; | ||
1472 | return 0; | ||
1473 | |||
1474 | free_buffers: | ||
1475 | return try_to_free_buffers(page); | 1291 | return try_to_free_buffers(page); |
1476 | } | 1292 | } |
1477 | 1293 | ||
@@ -1481,9 +1297,9 @@ __xfs_get_blocks( | |||
1481 | sector_t iblock, | 1297 | sector_t iblock, |
1482 | struct buffer_head *bh_result, | 1298 | struct buffer_head *bh_result, |
1483 | int create, | 1299 | int create, |
1484 | int direct, | 1300 | int direct) |
1485 | bmapi_flags_t flags) | ||
1486 | { | 1301 | { |
1302 | int flags = create ? BMAPI_WRITE : BMAPI_READ; | ||
1487 | struct xfs_bmbt_irec imap; | 1303 | struct xfs_bmbt_irec imap; |
1488 | xfs_off_t offset; | 1304 | xfs_off_t offset; |
1489 | ssize_t size; | 1305 | ssize_t size; |
@@ -1498,8 +1314,11 @@ __xfs_get_blocks( | |||
1498 | if (!create && direct && offset >= i_size_read(inode)) | 1314 | if (!create && direct && offset >= i_size_read(inode)) |
1499 | return 0; | 1315 | return 0; |
1500 | 1316 | ||
1501 | error = xfs_iomap(XFS_I(inode), offset, size, | 1317 | if (direct && create) |
1502 | create ? flags : BMAPI_READ, &imap, &nimap, &new); | 1318 | flags |= BMAPI_DIRECT; |
1319 | |||
1320 | error = xfs_iomap(XFS_I(inode), offset, size, flags, &imap, &nimap, | ||
1321 | &new); | ||
1503 | if (error) | 1322 | if (error) |
1504 | return -error; | 1323 | return -error; |
1505 | if (nimap == 0) | 1324 | if (nimap == 0) |
@@ -1579,8 +1398,7 @@ xfs_get_blocks( | |||
1579 | struct buffer_head *bh_result, | 1398 | struct buffer_head *bh_result, |
1580 | int create) | 1399 | int create) |
1581 | { | 1400 | { |
1582 | return __xfs_get_blocks(inode, iblock, | 1401 | return __xfs_get_blocks(inode, iblock, bh_result, create, 0); |
1583 | bh_result, create, 0, BMAPI_WRITE); | ||
1584 | } | 1402 | } |
1585 | 1403 | ||
1586 | STATIC int | 1404 | STATIC int |
@@ -1590,61 +1408,59 @@ xfs_get_blocks_direct( | |||
1590 | struct buffer_head *bh_result, | 1408 | struct buffer_head *bh_result, |
1591 | int create) | 1409 | int create) |
1592 | { | 1410 | { |
1593 | return __xfs_get_blocks(inode, iblock, | 1411 | return __xfs_get_blocks(inode, iblock, bh_result, create, 1); |
1594 | bh_result, create, 1, BMAPI_WRITE|BMAPI_DIRECT); | ||
1595 | } | 1412 | } |
1596 | 1413 | ||
1414 | /* | ||
1415 | * Complete a direct I/O write request. | ||
1416 | * | ||
1417 | * If the private argument is non-NULL __xfs_get_blocks signals us that we | ||
1418 | * need to issue a transaction to convert the range from unwritten to written | ||
1419 | * extents. In case this is regular synchronous I/O we just call xfs_end_io | ||
1420 | * to do this and we are done. But in case this was a successfull AIO | ||
1421 | * request this handler is called from interrupt context, from which we | ||
1422 | * can't start transactions. In that case offload the I/O completion to | ||
1423 | * the workqueues we also use for buffered I/O completion. | ||
1424 | */ | ||
1597 | STATIC void | 1425 | STATIC void |
1598 | xfs_end_io_direct( | 1426 | xfs_end_io_direct_write( |
1599 | struct kiocb *iocb, | 1427 | struct kiocb *iocb, |
1600 | loff_t offset, | 1428 | loff_t offset, |
1601 | ssize_t size, | 1429 | ssize_t size, |
1602 | void *private) | 1430 | void *private, |
1431 | int ret, | ||
1432 | bool is_async) | ||
1603 | { | 1433 | { |
1604 | xfs_ioend_t *ioend = iocb->private; | 1434 | struct xfs_ioend *ioend = iocb->private; |
1605 | 1435 | ||
1606 | /* | 1436 | /* |
1607 | * Non-NULL private data means we need to issue a transaction to | 1437 | * blockdev_direct_IO can return an error even after the I/O |
1608 | * convert a range from unwritten to written extents. This needs | 1438 | * completion handler was called. Thus we need to protect |
1609 | * to happen from process context but aio+dio I/O completion | 1439 | * against double-freeing. |
1610 | * happens from irq context so we need to defer it to a workqueue. | ||
1611 | * This is not necessary for synchronous direct I/O, but we do | ||
1612 | * it anyway to keep the code uniform and simpler. | ||
1613 | * | ||
1614 | * Well, if only it were that simple. Because synchronous direct I/O | ||
1615 | * requires extent conversion to occur *before* we return to userspace, | ||
1616 | * we have to wait for extent conversion to complete. Look at the | ||
1617 | * iocb that has been passed to us to determine if this is AIO or | ||
1618 | * not. If it is synchronous, tell xfs_finish_ioend() to kick the | ||
1619 | * workqueue and wait for it to complete. | ||
1620 | * | ||
1621 | * The core direct I/O code might be changed to always call the | ||
1622 | * completion handler in the future, in which case all this can | ||
1623 | * go away. | ||
1624 | */ | 1440 | */ |
1441 | iocb->private = NULL; | ||
1442 | |||
1625 | ioend->io_offset = offset; | 1443 | ioend->io_offset = offset; |
1626 | ioend->io_size = size; | 1444 | ioend->io_size = size; |
1627 | if (ioend->io_type == IO_READ) { | 1445 | if (private && size > 0) |
1628 | xfs_finish_ioend(ioend, 0); | 1446 | ioend->io_type = IO_UNWRITTEN; |
1629 | } else if (private && size > 0) { | 1447 | |
1630 | xfs_finish_ioend(ioend, is_sync_kiocb(iocb)); | 1448 | if (is_async) { |
1631 | } else { | ||
1632 | /* | 1449 | /* |
1633 | * A direct I/O write ioend starts it's life in unwritten | 1450 | * If we are converting an unwritten extent we need to delay |
1634 | * state in case they map an unwritten extent. This write | 1451 | * the AIO completion until after the unwrittent extent |
1635 | * didn't map an unwritten extent so switch it's completion | 1452 | * conversion has completed, otherwise do it ASAP. |
1636 | * handler. | ||
1637 | */ | 1453 | */ |
1638 | ioend->io_type = IO_NEW; | 1454 | if (ioend->io_type == IO_UNWRITTEN) { |
1639 | xfs_finish_ioend(ioend, 0); | 1455 | ioend->io_iocb = iocb; |
1456 | ioend->io_result = ret; | ||
1457 | } else { | ||
1458 | aio_complete(iocb, ret, 0); | ||
1459 | } | ||
1460 | xfs_finish_ioend(ioend); | ||
1461 | } else { | ||
1462 | xfs_finish_ioend_sync(ioend); | ||
1640 | } | 1463 | } |
1641 | |||
1642 | /* | ||
1643 | * blockdev_direct_IO can return an error even after the I/O | ||
1644 | * completion handler was called. Thus we need to protect | ||
1645 | * against double-freeing. | ||
1646 | */ | ||
1647 | iocb->private = NULL; | ||
1648 | } | 1464 | } |
1649 | 1465 | ||
1650 | STATIC ssize_t | 1466 | STATIC ssize_t |
@@ -1655,23 +1471,26 @@ xfs_vm_direct_IO( | |||
1655 | loff_t offset, | 1471 | loff_t offset, |
1656 | unsigned long nr_segs) | 1472 | unsigned long nr_segs) |
1657 | { | 1473 | { |
1658 | struct file *file = iocb->ki_filp; | 1474 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
1659 | struct inode *inode = file->f_mapping->host; | 1475 | struct block_device *bdev = xfs_find_bdev_for_inode(inode); |
1660 | struct block_device *bdev; | 1476 | ssize_t ret; |
1661 | ssize_t ret; | 1477 | |
1662 | 1478 | if (rw & WRITE) { | |
1663 | bdev = xfs_find_bdev_for_inode(inode); | 1479 | iocb->private = xfs_alloc_ioend(inode, IO_NEW); |
1664 | 1480 | ||
1665 | iocb->private = xfs_alloc_ioend(inode, rw == WRITE ? | 1481 | ret = blockdev_direct_IO_no_locking(rw, iocb, inode, bdev, iov, |
1666 | IO_UNWRITTEN : IO_READ); | 1482 | offset, nr_segs, |
1667 | 1483 | xfs_get_blocks_direct, | |
1668 | ret = blockdev_direct_IO_no_locking(rw, iocb, inode, bdev, iov, | 1484 | xfs_end_io_direct_write); |
1669 | offset, nr_segs, | 1485 | if (ret != -EIOCBQUEUED && iocb->private) |
1670 | xfs_get_blocks_direct, | 1486 | xfs_destroy_ioend(iocb->private); |
1671 | xfs_end_io_direct); | 1487 | } else { |
1488 | ret = blockdev_direct_IO_no_locking(rw, iocb, inode, bdev, iov, | ||
1489 | offset, nr_segs, | ||
1490 | xfs_get_blocks_direct, | ||
1491 | NULL); | ||
1492 | } | ||
1672 | 1493 | ||
1673 | if (unlikely(ret != -EIOCBQUEUED && iocb->private)) | ||
1674 | xfs_destroy_ioend(iocb->private); | ||
1675 | return ret; | 1494 | return ret; |
1676 | } | 1495 | } |
1677 | 1496 | ||
@@ -1686,8 +1505,8 @@ xfs_vm_write_begin( | |||
1686 | void **fsdata) | 1505 | void **fsdata) |
1687 | { | 1506 | { |
1688 | *pagep = NULL; | 1507 | *pagep = NULL; |
1689 | return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 1508 | return block_write_begin(file, mapping, pos, len, flags | AOP_FLAG_NOFS, |
1690 | xfs_get_blocks); | 1509 | pagep, fsdata, xfs_get_blocks); |
1691 | } | 1510 | } |
1692 | 1511 | ||
1693 | STATIC sector_t | 1512 | STATIC sector_t |
@@ -1698,7 +1517,7 @@ xfs_vm_bmap( | |||
1698 | struct inode *inode = (struct inode *)mapping->host; | 1517 | struct inode *inode = (struct inode *)mapping->host; |
1699 | struct xfs_inode *ip = XFS_I(inode); | 1518 | struct xfs_inode *ip = XFS_I(inode); |
1700 | 1519 | ||
1701 | xfs_itrace_entry(XFS_I(inode)); | 1520 | trace_xfs_vm_bmap(XFS_I(inode)); |
1702 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 1521 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
1703 | xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF); | 1522 | xfs_flush_pages(ip, (xfs_off_t)0, -1, 0, FI_REMAPF); |
1704 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | 1523 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); |
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 4cfc6ea87df8..c5057fb6237a 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h | |||
@@ -37,6 +37,8 @@ typedef struct xfs_ioend { | |||
37 | size_t io_size; /* size of the extent */ | 37 | size_t io_size; /* size of the extent */ |
38 | xfs_off_t io_offset; /* offset in the file */ | 38 | xfs_off_t io_offset; /* offset in the file */ |
39 | struct work_struct io_work; /* xfsdatad work queue */ | 39 | struct work_struct io_work; /* xfsdatad work queue */ |
40 | struct kiocb *io_iocb; | ||
41 | int io_result; | ||
40 | } xfs_ioend_t; | 42 | } xfs_ioend_t; |
41 | 43 | ||
42 | extern const struct address_space_operations xfs_address_space_operations; | 44 | extern const struct address_space_operations xfs_address_space_operations; |
@@ -45,6 +47,6 @@ extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); | |||
45 | extern void xfs_ioend_init(void); | 47 | extern void xfs_ioend_init(void); |
46 | extern void xfs_ioend_wait(struct xfs_inode *); | 48 | extern void xfs_ioend_wait(struct xfs_inode *); |
47 | 49 | ||
48 | extern void xfs_count_page_state(struct page *, int *, int *, int *); | 50 | extern void xfs_count_page_state(struct page *, int *, int *); |
49 | 51 | ||
50 | #endif /* __XFS_AOPS_H__ */ | 52 | #endif /* __XFS_AOPS_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 649ade8ef598..ea79072f5210 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -39,13 +39,12 @@ | |||
39 | #include "xfs_inum.h" | 39 | #include "xfs_inum.h" |
40 | #include "xfs_log.h" | 40 | #include "xfs_log.h" |
41 | #include "xfs_ag.h" | 41 | #include "xfs_ag.h" |
42 | #include "xfs_dmapi.h" | ||
43 | #include "xfs_mount.h" | 42 | #include "xfs_mount.h" |
44 | #include "xfs_trace.h" | 43 | #include "xfs_trace.h" |
45 | 44 | ||
46 | static kmem_zone_t *xfs_buf_zone; | 45 | static kmem_zone_t *xfs_buf_zone; |
47 | STATIC int xfsbufd(void *); | 46 | STATIC int xfsbufd(void *); |
48 | STATIC int xfsbufd_wakeup(int, gfp_t); | 47 | STATIC int xfsbufd_wakeup(struct shrinker *, int, gfp_t); |
49 | STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int); | 48 | STATIC void xfs_buf_delwri_queue(xfs_buf_t *, int); |
50 | static struct shrinker xfs_buf_shake = { | 49 | static struct shrinker xfs_buf_shake = { |
51 | .shrink = xfsbufd_wakeup, | 50 | .shrink = xfsbufd_wakeup, |
@@ -340,7 +339,7 @@ _xfs_buf_lookup_pages( | |||
340 | __func__, gfp_mask); | 339 | __func__, gfp_mask); |
341 | 340 | ||
342 | XFS_STATS_INC(xb_page_retries); | 341 | XFS_STATS_INC(xb_page_retries); |
343 | xfsbufd_wakeup(0, gfp_mask); | 342 | xfsbufd_wakeup(NULL, 0, gfp_mask); |
344 | congestion_wait(BLK_RW_ASYNC, HZ/50); | 343 | congestion_wait(BLK_RW_ASYNC, HZ/50); |
345 | goto retry; | 344 | goto retry; |
346 | } | 345 | } |
@@ -579,9 +578,9 @@ _xfs_buf_read( | |||
579 | XBF_READ_AHEAD | _XBF_RUN_QUEUES); | 578 | XBF_READ_AHEAD | _XBF_RUN_QUEUES); |
580 | 579 | ||
581 | status = xfs_buf_iorequest(bp); | 580 | status = xfs_buf_iorequest(bp); |
582 | if (!status && !(flags & XBF_ASYNC)) | 581 | if (status || XFS_BUF_ISERROR(bp) || (flags & XBF_ASYNC)) |
583 | status = xfs_buf_iowait(bp); | 582 | return status; |
584 | return status; | 583 | return xfs_buf_iowait(bp); |
585 | } | 584 | } |
586 | 585 | ||
587 | xfs_buf_t * | 586 | xfs_buf_t * |
@@ -897,36 +896,6 @@ xfs_buf_unlock( | |||
897 | trace_xfs_buf_unlock(bp, _RET_IP_); | 896 | trace_xfs_buf_unlock(bp, _RET_IP_); |
898 | } | 897 | } |
899 | 898 | ||
900 | |||
901 | /* | ||
902 | * Pinning Buffer Storage in Memory | ||
903 | * Ensure that no attempt to force a buffer to disk will succeed. | ||
904 | */ | ||
905 | void | ||
906 | xfs_buf_pin( | ||
907 | xfs_buf_t *bp) | ||
908 | { | ||
909 | trace_xfs_buf_pin(bp, _RET_IP_); | ||
910 | atomic_inc(&bp->b_pin_count); | ||
911 | } | ||
912 | |||
913 | void | ||
914 | xfs_buf_unpin( | ||
915 | xfs_buf_t *bp) | ||
916 | { | ||
917 | trace_xfs_buf_unpin(bp, _RET_IP_); | ||
918 | |||
919 | if (atomic_dec_and_test(&bp->b_pin_count)) | ||
920 | wake_up_all(&bp->b_waiters); | ||
921 | } | ||
922 | |||
923 | int | ||
924 | xfs_buf_ispin( | ||
925 | xfs_buf_t *bp) | ||
926 | { | ||
927 | return atomic_read(&bp->b_pin_count); | ||
928 | } | ||
929 | |||
930 | STATIC void | 899 | STATIC void |
931 | xfs_buf_wait_unpin( | 900 | xfs_buf_wait_unpin( |
932 | xfs_buf_t *bp) | 901 | xfs_buf_t *bp) |
@@ -1018,13 +987,12 @@ xfs_bwrite( | |||
1018 | { | 987 | { |
1019 | int error; | 988 | int error; |
1020 | 989 | ||
1021 | bp->b_strat = xfs_bdstrat_cb; | ||
1022 | bp->b_mount = mp; | 990 | bp->b_mount = mp; |
1023 | bp->b_flags |= XBF_WRITE; | 991 | bp->b_flags |= XBF_WRITE; |
1024 | bp->b_flags &= ~(XBF_ASYNC | XBF_READ); | 992 | bp->b_flags &= ~(XBF_ASYNC | XBF_READ); |
1025 | 993 | ||
1026 | xfs_buf_delwri_dequeue(bp); | 994 | xfs_buf_delwri_dequeue(bp); |
1027 | xfs_buf_iostrategy(bp); | 995 | xfs_bdstrat_cb(bp); |
1028 | 996 | ||
1029 | error = xfs_buf_iowait(bp); | 997 | error = xfs_buf_iowait(bp); |
1030 | if (error) | 998 | if (error) |
@@ -1040,7 +1008,6 @@ xfs_bdwrite( | |||
1040 | { | 1008 | { |
1041 | trace_xfs_buf_bdwrite(bp, _RET_IP_); | 1009 | trace_xfs_buf_bdwrite(bp, _RET_IP_); |
1042 | 1010 | ||
1043 | bp->b_strat = xfs_bdstrat_cb; | ||
1044 | bp->b_mount = mp; | 1011 | bp->b_mount = mp; |
1045 | 1012 | ||
1046 | bp->b_flags &= ~XBF_READ; | 1013 | bp->b_flags &= ~XBF_READ; |
@@ -1075,7 +1042,6 @@ xfs_bioerror( | |||
1075 | XFS_BUF_UNDONE(bp); | 1042 | XFS_BUF_UNDONE(bp); |
1076 | XFS_BUF_STALE(bp); | 1043 | XFS_BUF_STALE(bp); |
1077 | 1044 | ||
1078 | XFS_BUF_CLR_BDSTRAT_FUNC(bp); | ||
1079 | xfs_biodone(bp); | 1045 | xfs_biodone(bp); |
1080 | 1046 | ||
1081 | return EIO; | 1047 | return EIO; |
@@ -1105,7 +1071,6 @@ xfs_bioerror_relse( | |||
1105 | XFS_BUF_DONE(bp); | 1071 | XFS_BUF_DONE(bp); |
1106 | XFS_BUF_STALE(bp); | 1072 | XFS_BUF_STALE(bp); |
1107 | XFS_BUF_CLR_IODONE_FUNC(bp); | 1073 | XFS_BUF_CLR_IODONE_FUNC(bp); |
1108 | XFS_BUF_CLR_BDSTRAT_FUNC(bp); | ||
1109 | if (!(fl & XBF_ASYNC)) { | 1074 | if (!(fl & XBF_ASYNC)) { |
1110 | /* | 1075 | /* |
1111 | * Mark b_error and B_ERROR _both_. | 1076 | * Mark b_error and B_ERROR _both_. |
@@ -1311,8 +1276,19 @@ submit_io: | |||
1311 | if (size) | 1276 | if (size) |
1312 | goto next_chunk; | 1277 | goto next_chunk; |
1313 | } else { | 1278 | } else { |
1314 | bio_put(bio); | 1279 | /* |
1280 | * if we get here, no pages were added to the bio. However, | ||
1281 | * we can't just error out here - if the pages are locked then | ||
1282 | * we have to unlock them otherwise we can hang on a later | ||
1283 | * access to the page. | ||
1284 | */ | ||
1315 | xfs_buf_ioerror(bp, EIO); | 1285 | xfs_buf_ioerror(bp, EIO); |
1286 | if (bp->b_flags & _XBF_PAGE_LOCKED) { | ||
1287 | int i; | ||
1288 | for (i = 0; i < bp->b_page_count; i++) | ||
1289 | unlock_page(bp->b_pages[i]); | ||
1290 | } | ||
1291 | bio_put(bio); | ||
1316 | } | 1292 | } |
1317 | } | 1293 | } |
1318 | 1294 | ||
@@ -1762,6 +1738,7 @@ xfs_buf_runall_queues( | |||
1762 | 1738 | ||
1763 | STATIC int | 1739 | STATIC int |
1764 | xfsbufd_wakeup( | 1740 | xfsbufd_wakeup( |
1741 | struct shrinker *shrink, | ||
1765 | int priority, | 1742 | int priority, |
1766 | gfp_t mask) | 1743 | gfp_t mask) |
1767 | { | 1744 | { |
@@ -1803,7 +1780,7 @@ xfs_buf_delwri_split( | |||
1803 | trace_xfs_buf_delwri_split(bp, _RET_IP_); | 1780 | trace_xfs_buf_delwri_split(bp, _RET_IP_); |
1804 | ASSERT(bp->b_flags & XBF_DELWRI); | 1781 | ASSERT(bp->b_flags & XBF_DELWRI); |
1805 | 1782 | ||
1806 | if (!xfs_buf_ispin(bp) && !xfs_buf_cond_lock(bp)) { | 1783 | if (!XFS_BUF_ISPINNED(bp) && !xfs_buf_cond_lock(bp)) { |
1807 | if (!force && | 1784 | if (!force && |
1808 | time_before(jiffies, bp->b_queuetime + age)) { | 1785 | time_before(jiffies, bp->b_queuetime + age)) { |
1809 | xfs_buf_unlock(bp); | 1786 | xfs_buf_unlock(bp); |
@@ -1888,7 +1865,7 @@ xfsbufd( | |||
1888 | struct xfs_buf *bp; | 1865 | struct xfs_buf *bp; |
1889 | bp = list_first_entry(&tmp, struct xfs_buf, b_list); | 1866 | bp = list_first_entry(&tmp, struct xfs_buf, b_list); |
1890 | list_del_init(&bp->b_list); | 1867 | list_del_init(&bp->b_list); |
1891 | xfs_buf_iostrategy(bp); | 1868 | xfs_bdstrat_cb(bp); |
1892 | count++; | 1869 | count++; |
1893 | } | 1870 | } |
1894 | if (count) | 1871 | if (count) |
@@ -1935,7 +1912,7 @@ xfs_flush_buftarg( | |||
1935 | bp->b_flags &= ~XBF_ASYNC; | 1912 | bp->b_flags &= ~XBF_ASYNC; |
1936 | list_add(&bp->b_list, &wait_list); | 1913 | list_add(&bp->b_list, &wait_list); |
1937 | } | 1914 | } |
1938 | xfs_buf_iostrategy(bp); | 1915 | xfs_bdstrat_cb(bp); |
1939 | } | 1916 | } |
1940 | 1917 | ||
1941 | if (wait) { | 1918 | if (wait) { |
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index 5fbecefa5dfd..d072e5ff923b 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h | |||
@@ -44,57 +44,57 @@ typedef enum { | |||
44 | XBRW_ZERO = 3, /* Zero target memory */ | 44 | XBRW_ZERO = 3, /* Zero target memory */ |
45 | } xfs_buf_rw_t; | 45 | } xfs_buf_rw_t; |
46 | 46 | ||
47 | typedef enum { | 47 | #define XBF_READ (1 << 0) /* buffer intended for reading from device */ |
48 | XBF_READ = (1 << 0), /* buffer intended for reading from device */ | 48 | #define XBF_WRITE (1 << 1) /* buffer intended for writing to device */ |
49 | XBF_WRITE = (1 << 1), /* buffer intended for writing to device */ | 49 | #define XBF_MAPPED (1 << 2) /* buffer mapped (b_addr valid) */ |
50 | XBF_MAPPED = (1 << 2), /* buffer mapped (b_addr valid) */ | 50 | #define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */ |
51 | XBF_ASYNC = (1 << 4), /* initiator will not wait for completion */ | 51 | #define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */ |
52 | XBF_DONE = (1 << 5), /* all pages in the buffer uptodate */ | 52 | #define XBF_DELWRI (1 << 6) /* buffer has dirty pages */ |
53 | XBF_DELWRI = (1 << 6), /* buffer has dirty pages */ | 53 | #define XBF_STALE (1 << 7) /* buffer has been staled, do not find it */ |
54 | XBF_STALE = (1 << 7), /* buffer has been staled, do not find it */ | 54 | #define XBF_FS_MANAGED (1 << 8) /* filesystem controls freeing memory */ |
55 | XBF_FS_MANAGED = (1 << 8), /* filesystem controls freeing memory */ | 55 | #define XBF_ORDERED (1 << 11)/* use ordered writes */ |
56 | XBF_ORDERED = (1 << 11), /* use ordered writes */ | 56 | #define XBF_READ_AHEAD (1 << 12)/* asynchronous read-ahead */ |
57 | XBF_READ_AHEAD = (1 << 12), /* asynchronous read-ahead */ | 57 | #define XBF_LOG_BUFFER (1 << 13)/* this is a buffer used for the log */ |
58 | XBF_LOG_BUFFER = (1 << 13), /* this is a buffer used for the log */ | 58 | |
59 | 59 | /* flags used only as arguments to access routines */ | |
60 | /* flags used only as arguments to access routines */ | 60 | #define XBF_LOCK (1 << 14)/* lock requested */ |
61 | XBF_LOCK = (1 << 14), /* lock requested */ | 61 | #define XBF_TRYLOCK (1 << 15)/* lock requested, but do not wait */ |
62 | XBF_TRYLOCK = (1 << 15), /* lock requested, but do not wait */ | 62 | #define XBF_DONT_BLOCK (1 << 16)/* do not block in current thread */ |
63 | XBF_DONT_BLOCK = (1 << 16), /* do not block in current thread */ | 63 | |
64 | 64 | /* flags used only internally */ | |
65 | /* flags used only internally */ | 65 | #define _XBF_PAGE_CACHE (1 << 17)/* backed by pagecache */ |
66 | _XBF_PAGE_CACHE = (1 << 17),/* backed by pagecache */ | 66 | #define _XBF_PAGES (1 << 18)/* backed by refcounted pages */ |
67 | _XBF_PAGES = (1 << 18), /* backed by refcounted pages */ | 67 | #define _XBF_RUN_QUEUES (1 << 19)/* run block device task queue */ |
68 | _XBF_RUN_QUEUES = (1 << 19),/* run block device task queue */ | 68 | #define _XBF_DELWRI_Q (1 << 21)/* buffer on delwri queue */ |
69 | _XBF_DELWRI_Q = (1 << 21), /* buffer on delwri queue */ | 69 | |
70 | 70 | /* | |
71 | /* | 71 | * Special flag for supporting metadata blocks smaller than a FSB. |
72 | * Special flag for supporting metadata blocks smaller than a FSB. | 72 | * |
73 | * | 73 | * In this case we can have multiple xfs_buf_t on a single page and |
74 | * In this case we can have multiple xfs_buf_t on a single page and | 74 | * need to lock out concurrent xfs_buf_t readers as they only |
75 | * need to lock out concurrent xfs_buf_t readers as they only | 75 | * serialise access to the buffer. |
76 | * serialise access to the buffer. | 76 | * |
77 | * | 77 | * If the FSB size >= PAGE_CACHE_SIZE case, we have no serialisation |
78 | * If the FSB size >= PAGE_CACHE_SIZE case, we have no serialisation | 78 | * between reads of the page. Hence we can have one thread read the |
79 | * between reads of the page. Hence we can have one thread read the | 79 | * page and modify it, but then race with another thread that thinks |
80 | * page and modify it, but then race with another thread that thinks | 80 | * the page is not up-to-date and hence reads it again. |
81 | * the page is not up-to-date and hence reads it again. | 81 | * |
82 | * | 82 | * The result is that the first modifcation to the page is lost. |
83 | * The result is that the first modifcation to the page is lost. | 83 | * This sort of AGF/AGI reading race can happen when unlinking inodes |
84 | * This sort of AGF/AGI reading race can happen when unlinking inodes | 84 | * that require truncation and results in the AGI unlinked list |
85 | * that require truncation and results in the AGI unlinked list | 85 | * modifications being lost. |
86 | * modifications being lost. | 86 | */ |
87 | */ | 87 | #define _XBF_PAGE_LOCKED (1 << 22) |
88 | _XBF_PAGE_LOCKED = (1 << 22), | 88 | |
89 | 89 | /* | |
90 | /* | 90 | * If we try a barrier write, but it fails we have to communicate |
91 | * If we try a barrier write, but it fails we have to communicate | 91 | * this to the upper layers. Unfortunately b_error gets overwritten |
92 | * this to the upper layers. Unfortunately b_error gets overwritten | 92 | * when the buffer is re-issued so we have to add another flag to |
93 | * when the buffer is re-issued so we have to add another flag to | 93 | * keep this information. |
94 | * keep this information. | 94 | */ |
95 | */ | 95 | #define _XFS_BARRIER_FAILED (1 << 23) |
96 | _XFS_BARRIER_FAILED = (1 << 23), | 96 | |
97 | } xfs_buf_flags_t; | 97 | typedef unsigned int xfs_buf_flags_t; |
98 | 98 | ||
99 | #define XFS_BUF_FLAGS \ | 99 | #define XFS_BUF_FLAGS \ |
100 | { XBF_READ, "READ" }, \ | 100 | { XBF_READ, "READ" }, \ |
@@ -187,7 +187,6 @@ typedef struct xfs_buf { | |||
187 | atomic_t b_io_remaining; /* #outstanding I/O requests */ | 187 | atomic_t b_io_remaining; /* #outstanding I/O requests */ |
188 | xfs_buf_iodone_t b_iodone; /* I/O completion function */ | 188 | xfs_buf_iodone_t b_iodone; /* I/O completion function */ |
189 | xfs_buf_relse_t b_relse; /* releasing function */ | 189 | xfs_buf_relse_t b_relse; /* releasing function */ |
190 | xfs_buf_bdstrat_t b_strat; /* pre-write function */ | ||
191 | struct completion b_iowait; /* queue for I/O waiters */ | 190 | struct completion b_iowait; /* queue for I/O waiters */ |
192 | void *b_fspriv; | 191 | void *b_fspriv; |
193 | void *b_fspriv2; | 192 | void *b_fspriv2; |
@@ -245,11 +244,6 @@ extern int xfs_buf_iowait(xfs_buf_t *); | |||
245 | extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, | 244 | extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, |
246 | xfs_buf_rw_t); | 245 | xfs_buf_rw_t); |
247 | 246 | ||
248 | static inline int xfs_buf_iostrategy(xfs_buf_t *bp) | ||
249 | { | ||
250 | return bp->b_strat ? bp->b_strat(bp) : xfs_buf_iorequest(bp); | ||
251 | } | ||
252 | |||
253 | static inline int xfs_buf_geterror(xfs_buf_t *bp) | 247 | static inline int xfs_buf_geterror(xfs_buf_t *bp) |
254 | { | 248 | { |
255 | return bp ? bp->b_error : ENOMEM; | 249 | return bp ? bp->b_error : ENOMEM; |
@@ -258,11 +252,6 @@ static inline int xfs_buf_geterror(xfs_buf_t *bp) | |||
258 | /* Buffer Utility Routines */ | 252 | /* Buffer Utility Routines */ |
259 | extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t); | 253 | extern xfs_caddr_t xfs_buf_offset(xfs_buf_t *, size_t); |
260 | 254 | ||
261 | /* Pinning Buffer Storage in Memory */ | ||
262 | extern void xfs_buf_pin(xfs_buf_t *); | ||
263 | extern void xfs_buf_unpin(xfs_buf_t *); | ||
264 | extern int xfs_buf_ispin(xfs_buf_t *); | ||
265 | |||
266 | /* Delayed Write Buffer Routines */ | 255 | /* Delayed Write Buffer Routines */ |
267 | extern void xfs_buf_delwri_dequeue(xfs_buf_t *); | 256 | extern void xfs_buf_delwri_dequeue(xfs_buf_t *); |
268 | extern void xfs_buf_delwri_promote(xfs_buf_t *); | 257 | extern void xfs_buf_delwri_promote(xfs_buf_t *); |
@@ -326,8 +315,6 @@ extern void xfs_buf_terminate(void); | |||
326 | #define XFS_BUF_IODONE_FUNC(bp) ((bp)->b_iodone) | 315 | #define XFS_BUF_IODONE_FUNC(bp) ((bp)->b_iodone) |
327 | #define XFS_BUF_SET_IODONE_FUNC(bp, func) ((bp)->b_iodone = (func)) | 316 | #define XFS_BUF_SET_IODONE_FUNC(bp, func) ((bp)->b_iodone = (func)) |
328 | #define XFS_BUF_CLR_IODONE_FUNC(bp) ((bp)->b_iodone = NULL) | 317 | #define XFS_BUF_CLR_IODONE_FUNC(bp) ((bp)->b_iodone = NULL) |
329 | #define XFS_BUF_SET_BDSTRAT_FUNC(bp, func) ((bp)->b_strat = (func)) | ||
330 | #define XFS_BUF_CLR_BDSTRAT_FUNC(bp) ((bp)->b_strat = NULL) | ||
331 | 318 | ||
332 | #define XFS_BUF_FSPRIVATE(bp, type) ((type)(bp)->b_fspriv) | 319 | #define XFS_BUF_FSPRIVATE(bp, type) ((type)(bp)->b_fspriv) |
333 | #define XFS_BUF_SET_FSPRIVATE(bp, val) ((bp)->b_fspriv = (void*)(val)) | 320 | #define XFS_BUF_SET_FSPRIVATE(bp, val) ((bp)->b_fspriv = (void*)(val)) |
@@ -351,7 +338,7 @@ extern void xfs_buf_terminate(void); | |||
351 | #define XFS_BUF_SET_VTYPE(bp, type) do { } while (0) | 338 | #define XFS_BUF_SET_VTYPE(bp, type) do { } while (0) |
352 | #define XFS_BUF_SET_REF(bp, ref) do { } while (0) | 339 | #define XFS_BUF_SET_REF(bp, ref) do { } while (0) |
353 | 340 | ||
354 | #define XFS_BUF_ISPINNED(bp) xfs_buf_ispin(bp) | 341 | #define XFS_BUF_ISPINNED(bp) atomic_read(&((bp)->b_pin_count)) |
355 | 342 | ||
356 | #define XFS_BUF_VALUSEMA(bp) xfs_buf_lock_value(bp) | 343 | #define XFS_BUF_VALUSEMA(bp) xfs_buf_lock_value(bp) |
357 | #define XFS_BUF_CPSEMA(bp) (xfs_buf_cond_lock(bp) == 0) | 344 | #define XFS_BUF_CPSEMA(bp) (xfs_buf_cond_lock(bp) == 0) |
@@ -370,8 +357,6 @@ static inline void xfs_buf_relse(xfs_buf_t *bp) | |||
370 | xfs_buf_rele(bp); | 357 | xfs_buf_rele(bp); |
371 | } | 358 | } |
372 | 359 | ||
373 | #define xfs_bpin(bp) xfs_buf_pin(bp) | ||
374 | #define xfs_bunpin(bp) xfs_buf_unpin(bp) | ||
375 | #define xfs_biodone(bp) xfs_buf_ioend(bp, 0) | 360 | #define xfs_biodone(bp) xfs_buf_ioend(bp, 0) |
376 | 361 | ||
377 | #define xfs_biomove(bp, off, len, data, rw) \ | 362 | #define xfs_biomove(bp, off, len, data, rw) \ |
diff --git a/fs/xfs/linux-2.6/xfs_dmapi_priv.h b/fs/xfs/linux-2.6/xfs_dmapi_priv.h deleted file mode 100644 index a8b0b1685eed..000000000000 --- a/fs/xfs/linux-2.6/xfs_dmapi_priv.h +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_DMAPI_PRIV_H__ | ||
19 | #define __XFS_DMAPI_PRIV_H__ | ||
20 | |||
21 | /* | ||
22 | * Based on IO_ISDIRECT, decide which i_ flag is set. | ||
23 | */ | ||
24 | #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ | ||
25 | DM_FLAGS_IMUX : 0) | ||
26 | #define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) | ||
27 | |||
28 | #endif /*__XFS_DMAPI_PRIV_H__*/ | ||
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index e7839ee49e43..3764d74790ec 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c | |||
@@ -23,13 +23,13 @@ | |||
23 | #include "xfs_sb.h" | 23 | #include "xfs_sb.h" |
24 | #include "xfs_ag.h" | 24 | #include "xfs_ag.h" |
25 | #include "xfs_dir2.h" | 25 | #include "xfs_dir2.h" |
26 | #include "xfs_dmapi.h" | ||
27 | #include "xfs_mount.h" | 26 | #include "xfs_mount.h" |
28 | #include "xfs_export.h" | 27 | #include "xfs_export.h" |
29 | #include "xfs_vnodeops.h" | 28 | #include "xfs_vnodeops.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
32 | #include "xfs_inode_item.h" | 31 | #include "xfs_inode_item.h" |
32 | #include "xfs_trace.h" | ||
33 | 33 | ||
34 | /* | 34 | /* |
35 | * Note that we only accept fileids which are long enough rather than allow | 35 | * Note that we only accept fileids which are long enough rather than allow |
@@ -132,8 +132,7 @@ xfs_nfs_get_inode( | |||
132 | * fine and not an indication of a corrupted filesystem as clients can | 132 | * fine and not an indication of a corrupted filesystem as clients can |
133 | * send invalid file handles and we have to handle it gracefully.. | 133 | * send invalid file handles and we have to handle it gracefully.. |
134 | */ | 134 | */ |
135 | error = xfs_iget(mp, NULL, ino, XFS_IGET_UNTRUSTED, | 135 | error = xfs_iget(mp, NULL, ino, XFS_IGET_UNTRUSTED, 0, &ip); |
136 | XFS_ILOCK_SHARED, &ip); | ||
137 | if (error) { | 136 | if (error) { |
138 | /* | 137 | /* |
139 | * EINVAL means the inode cluster doesn't exist anymore. | 138 | * EINVAL means the inode cluster doesn't exist anymore. |
@@ -148,11 +147,10 @@ xfs_nfs_get_inode( | |||
148 | } | 147 | } |
149 | 148 | ||
150 | if (ip->i_d.di_gen != generation) { | 149 | if (ip->i_d.di_gen != generation) { |
151 | xfs_iput_new(ip, XFS_ILOCK_SHARED); | 150 | IRELE(ip); |
152 | return ERR_PTR(-ENOENT); | 151 | return ERR_PTR(-ENOENT); |
153 | } | 152 | } |
154 | 153 | ||
155 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
156 | return VFS_I(ip); | 154 | return VFS_I(ip); |
157 | } | 155 | } |
158 | 156 | ||
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 257a56b127cf..ba8ad422a165 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -22,23 +22,15 @@ | |||
22 | #include "xfs_inum.h" | 22 | #include "xfs_inum.h" |
23 | #include "xfs_sb.h" | 23 | #include "xfs_sb.h" |
24 | #include "xfs_ag.h" | 24 | #include "xfs_ag.h" |
25 | #include "xfs_dir2.h" | ||
26 | #include "xfs_trans.h" | 25 | #include "xfs_trans.h" |
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | 26 | #include "xfs_mount.h" |
29 | #include "xfs_bmap_btree.h" | 27 | #include "xfs_bmap_btree.h" |
30 | #include "xfs_alloc_btree.h" | ||
31 | #include "xfs_ialloc_btree.h" | ||
32 | #include "xfs_alloc.h" | 28 | #include "xfs_alloc.h" |
33 | #include "xfs_btree.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | ||
36 | #include "xfs_dinode.h" | 29 | #include "xfs_dinode.h" |
37 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
38 | #include "xfs_inode_item.h" | 31 | #include "xfs_inode_item.h" |
39 | #include "xfs_bmap.h" | 32 | #include "xfs_bmap.h" |
40 | #include "xfs_error.h" | 33 | #include "xfs_error.h" |
41 | #include "xfs_rw.h" | ||
42 | #include "xfs_vnodeops.h" | 34 | #include "xfs_vnodeops.h" |
43 | #include "xfs_da_btree.h" | 35 | #include "xfs_da_btree.h" |
44 | #include "xfs_ioctl.h" | 36 | #include "xfs_ioctl.h" |
@@ -108,7 +100,7 @@ xfs_file_fsync( | |||
108 | int error = 0; | 100 | int error = 0; |
109 | int log_flushed = 0; | 101 | int log_flushed = 0; |
110 | 102 | ||
111 | xfs_itrace_entry(ip); | 103 | trace_xfs_file_fsync(ip); |
112 | 104 | ||
113 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 105 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) |
114 | return -XFS_ERROR(EIO); | 106 | return -XFS_ERROR(EIO); |
@@ -166,8 +158,7 @@ xfs_file_fsync( | |||
166 | * transaction. So we play it safe and fire off the | 158 | * transaction. So we play it safe and fire off the |
167 | * transaction anyway. | 159 | * transaction anyway. |
168 | */ | 160 | */ |
169 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 161 | xfs_trans_ijoin(tp, ip); |
170 | xfs_trans_ihold(tp, ip); | ||
171 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 162 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
172 | xfs_trans_set_sync(tp); | 163 | xfs_trans_set_sync(tp); |
173 | error = _xfs_trans_commit(tp, 0, &log_flushed); | 164 | error = _xfs_trans_commit(tp, 0, &log_flushed); |
@@ -275,20 +266,6 @@ xfs_file_aio_read( | |||
275 | mutex_lock(&inode->i_mutex); | 266 | mutex_lock(&inode->i_mutex); |
276 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 267 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
277 | 268 | ||
278 | if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) { | ||
279 | int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags); | ||
280 | int iolock = XFS_IOLOCK_SHARED; | ||
281 | |||
282 | ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, ip, iocb->ki_pos, size, | ||
283 | dmflags, &iolock); | ||
284 | if (ret) { | ||
285 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | ||
286 | if (unlikely(ioflags & IO_ISDIRECT)) | ||
287 | mutex_unlock(&inode->i_mutex); | ||
288 | return ret; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | if (unlikely(ioflags & IO_ISDIRECT)) { | 269 | if (unlikely(ioflags & IO_ISDIRECT)) { |
293 | if (inode->i_mapping->nrpages) { | 270 | if (inode->i_mapping->nrpages) { |
294 | ret = -xfs_flushinval_pages(ip, | 271 | ret = -xfs_flushinval_pages(ip, |
@@ -321,7 +298,6 @@ xfs_file_splice_read( | |||
321 | unsigned int flags) | 298 | unsigned int flags) |
322 | { | 299 | { |
323 | struct xfs_inode *ip = XFS_I(infilp->f_mapping->host); | 300 | struct xfs_inode *ip = XFS_I(infilp->f_mapping->host); |
324 | struct xfs_mount *mp = ip->i_mount; | ||
325 | int ioflags = 0; | 301 | int ioflags = 0; |
326 | ssize_t ret; | 302 | ssize_t ret; |
327 | 303 | ||
@@ -335,18 +311,6 @@ xfs_file_splice_read( | |||
335 | 311 | ||
336 | xfs_ilock(ip, XFS_IOLOCK_SHARED); | 312 | xfs_ilock(ip, XFS_IOLOCK_SHARED); |
337 | 313 | ||
338 | if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) { | ||
339 | int iolock = XFS_IOLOCK_SHARED; | ||
340 | int error; | ||
341 | |||
342 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, *ppos, count, | ||
343 | FILP_DELAY_FLAG(infilp), &iolock); | ||
344 | if (error) { | ||
345 | xfs_iunlock(ip, XFS_IOLOCK_SHARED); | ||
346 | return -error; | ||
347 | } | ||
348 | } | ||
349 | |||
350 | trace_xfs_file_splice_read(ip, count, *ppos, ioflags); | 314 | trace_xfs_file_splice_read(ip, count, *ppos, ioflags); |
351 | 315 | ||
352 | ret = generic_file_splice_read(infilp, ppos, pipe, count, flags); | 316 | ret = generic_file_splice_read(infilp, ppos, pipe, count, flags); |
@@ -367,7 +331,6 @@ xfs_file_splice_write( | |||
367 | { | 331 | { |
368 | struct inode *inode = outfilp->f_mapping->host; | 332 | struct inode *inode = outfilp->f_mapping->host; |
369 | struct xfs_inode *ip = XFS_I(inode); | 333 | struct xfs_inode *ip = XFS_I(inode); |
370 | struct xfs_mount *mp = ip->i_mount; | ||
371 | xfs_fsize_t isize, new_size; | 334 | xfs_fsize_t isize, new_size; |
372 | int ioflags = 0; | 335 | int ioflags = 0; |
373 | ssize_t ret; | 336 | ssize_t ret; |
@@ -382,18 +345,6 @@ xfs_file_splice_write( | |||
382 | 345 | ||
383 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | 346 | xfs_ilock(ip, XFS_IOLOCK_EXCL); |
384 | 347 | ||
385 | if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) { | ||
386 | int iolock = XFS_IOLOCK_EXCL; | ||
387 | int error; | ||
388 | |||
389 | error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip, *ppos, count, | ||
390 | FILP_DELAY_FLAG(outfilp), &iolock); | ||
391 | if (error) { | ||
392 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
393 | return -error; | ||
394 | } | ||
395 | } | ||
396 | |||
397 | new_size = *ppos + count; | 348 | new_size = *ppos + count; |
398 | 349 | ||
399 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 350 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
@@ -463,7 +414,7 @@ xfs_zero_last_block( | |||
463 | last_fsb = XFS_B_TO_FSBT(mp, isize); | 414 | last_fsb = XFS_B_TO_FSBT(mp, isize); |
464 | nimaps = 1; | 415 | nimaps = 1; |
465 | error = xfs_bmapi(NULL, ip, last_fsb, 1, 0, NULL, 0, &imap, | 416 | error = xfs_bmapi(NULL, ip, last_fsb, 1, 0, NULL, 0, &imap, |
466 | &nimaps, NULL, NULL); | 417 | &nimaps, NULL); |
467 | if (error) { | 418 | if (error) { |
468 | return error; | 419 | return error; |
469 | } | 420 | } |
@@ -558,7 +509,7 @@ xfs_zero_eof( | |||
558 | nimaps = 1; | 509 | nimaps = 1; |
559 | zero_count_fsb = end_zero_fsb - start_zero_fsb + 1; | 510 | zero_count_fsb = end_zero_fsb - start_zero_fsb + 1; |
560 | error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb, | 511 | error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb, |
561 | 0, NULL, 0, &imap, &nimaps, NULL, NULL); | 512 | 0, NULL, 0, &imap, &nimaps, NULL); |
562 | if (error) { | 513 | if (error) { |
563 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL)); | 514 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL)); |
564 | return error; | 515 | return error; |
@@ -627,7 +578,6 @@ xfs_file_aio_write( | |||
627 | int ioflags = 0; | 578 | int ioflags = 0; |
628 | xfs_fsize_t isize, new_size; | 579 | xfs_fsize_t isize, new_size; |
629 | int iolock; | 580 | int iolock; |
630 | int eventsent = 0; | ||
631 | size_t ocount = 0, count; | 581 | size_t ocount = 0, count; |
632 | int need_i_mutex; | 582 | int need_i_mutex; |
633 | 583 | ||
@@ -673,33 +623,6 @@ start: | |||
673 | goto out_unlock_mutex; | 623 | goto out_unlock_mutex; |
674 | } | 624 | } |
675 | 625 | ||
676 | if ((DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && | ||
677 | !(ioflags & IO_INVIS) && !eventsent)) { | ||
678 | int dmflags = FILP_DELAY_FLAG(file); | ||
679 | |||
680 | if (need_i_mutex) | ||
681 | dmflags |= DM_FLAGS_IMUX; | ||
682 | |||
683 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
684 | error = XFS_SEND_DATA(ip->i_mount, DM_EVENT_WRITE, ip, | ||
685 | pos, count, dmflags, &iolock); | ||
686 | if (error) { | ||
687 | goto out_unlock_internal; | ||
688 | } | ||
689 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
690 | eventsent = 1; | ||
691 | |||
692 | /* | ||
693 | * The iolock was dropped and reacquired in XFS_SEND_DATA | ||
694 | * so we have to recheck the size when appending. | ||
695 | * We will only "goto start;" once, since having sent the | ||
696 | * event prevents another call to XFS_SEND_DATA, which is | ||
697 | * what allows the size to change in the first place. | ||
698 | */ | ||
699 | if ((file->f_flags & O_APPEND) && pos != ip->i_size) | ||
700 | goto start; | ||
701 | } | ||
702 | |||
703 | if (ioflags & IO_ISDIRECT) { | 626 | if (ioflags & IO_ISDIRECT) { |
704 | xfs_buftarg_t *target = | 627 | xfs_buftarg_t *target = |
705 | XFS_IS_REALTIME_INODE(ip) ? | 628 | XFS_IS_REALTIME_INODE(ip) ? |
@@ -830,22 +753,6 @@ write_retry: | |||
830 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 753 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
831 | } | 754 | } |
832 | 755 | ||
833 | if (ret == -ENOSPC && | ||
834 | DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) { | ||
835 | xfs_iunlock(ip, iolock); | ||
836 | if (need_i_mutex) | ||
837 | mutex_unlock(&inode->i_mutex); | ||
838 | error = XFS_SEND_NAMESP(ip->i_mount, DM_EVENT_NOSPACE, ip, | ||
839 | DM_RIGHT_NULL, ip, DM_RIGHT_NULL, NULL, NULL, | ||
840 | 0, 0, 0); /* Delay flag intentionally unused */ | ||
841 | if (need_i_mutex) | ||
842 | mutex_lock(&inode->i_mutex); | ||
843 | xfs_ilock(ip, iolock); | ||
844 | if (error) | ||
845 | goto out_unlock_internal; | ||
846 | goto start; | ||
847 | } | ||
848 | |||
849 | error = -ret; | 756 | error = -ret; |
850 | if (ret <= 0) | 757 | if (ret <= 0) |
851 | goto out_unlock_internal; | 758 | goto out_unlock_internal; |
@@ -1014,9 +921,6 @@ const struct file_operations xfs_file_operations = { | |||
1014 | .open = xfs_file_open, | 921 | .open = xfs_file_open, |
1015 | .release = xfs_file_release, | 922 | .release = xfs_file_release, |
1016 | .fsync = xfs_file_fsync, | 923 | .fsync = xfs_file_fsync, |
1017 | #ifdef HAVE_FOP_OPEN_EXEC | ||
1018 | .open_exec = xfs_file_open_exec, | ||
1019 | #endif | ||
1020 | }; | 924 | }; |
1021 | 925 | ||
1022 | const struct file_operations xfs_dir_file_operations = { | 926 | const struct file_operations xfs_dir_file_operations = { |
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c index b6918d76bc7b..1f279b012f94 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/linux-2.6/xfs_fs_subr.c | |||
@@ -21,10 +21,6 @@ | |||
21 | #include "xfs_inode.h" | 21 | #include "xfs_inode.h" |
22 | #include "xfs_trace.h" | 22 | #include "xfs_trace.h" |
23 | 23 | ||
24 | int fs_noerr(void) { return 0; } | ||
25 | int fs_nosys(void) { return ENOSYS; } | ||
26 | void fs_noval(void) { return; } | ||
27 | |||
28 | /* | 24 | /* |
29 | * note: all filemap functions return negative error codes. These | 25 | * note: all filemap functions return negative error codes. These |
30 | * need to be inverted before returning to the xfs core functions. | 26 | * need to be inverted before returning to the xfs core functions. |
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.h b/fs/xfs/linux-2.6/xfs_fs_subr.h deleted file mode 100644 index 82bb19b2599e..000000000000 --- a/fs/xfs/linux-2.6/xfs_fs_subr.h +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_FS_SUBR_H__ | ||
19 | #define __XFS_FS_SUBR_H__ | ||
20 | |||
21 | extern int fs_noerr(void); | ||
22 | extern int fs_nosys(void); | ||
23 | extern void fs_noval(void); | ||
24 | |||
25 | #endif /* __XFS_FS_SUBR_H__ */ | ||
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index e59a81062830..237f5ffb2ee8 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -23,24 +23,15 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | ||
27 | #include "xfs_alloc.h" | 26 | #include "xfs_alloc.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | ||
32 | #include "xfs_ialloc_btree.h" | ||
33 | #include "xfs_attr_sf.h" | ||
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_dinode.h" | 29 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
37 | #include "xfs_ioctl.h" | 31 | #include "xfs_ioctl.h" |
38 | #include "xfs_btree.h" | ||
39 | #include "xfs_ialloc.h" | ||
40 | #include "xfs_rtalloc.h" | 32 | #include "xfs_rtalloc.h" |
41 | #include "xfs_itable.h" | 33 | #include "xfs_itable.h" |
42 | #include "xfs_error.h" | 34 | #include "xfs_error.h" |
43 | #include "xfs_rw.h" | ||
44 | #include "xfs_attr.h" | 35 | #include "xfs_attr.h" |
45 | #include "xfs_bmap.h" | 36 | #include "xfs_bmap.h" |
46 | #include "xfs_buf_item.h" | 37 | #include "xfs_buf_item.h" |
@@ -908,7 +899,7 @@ xfs_ioctl_setattr( | |||
908 | struct xfs_dquot *olddquot = NULL; | 899 | struct xfs_dquot *olddquot = NULL; |
909 | int code; | 900 | int code; |
910 | 901 | ||
911 | xfs_itrace_entry(ip); | 902 | trace_xfs_ioctl_setattr(ip); |
912 | 903 | ||
913 | if (mp->m_flags & XFS_MOUNT_RDONLY) | 904 | if (mp->m_flags & XFS_MOUNT_RDONLY) |
914 | return XFS_ERROR(EROFS); | 905 | return XFS_ERROR(EROFS); |
@@ -1043,8 +1034,7 @@ xfs_ioctl_setattr( | |||
1043 | } | 1034 | } |
1044 | } | 1035 | } |
1045 | 1036 | ||
1046 | xfs_trans_ijoin(tp, ip, lock_flags); | 1037 | xfs_trans_ijoin(tp, ip); |
1047 | xfs_trans_ihold(tp, ip); | ||
1048 | 1038 | ||
1049 | /* | 1039 | /* |
1050 | * Change file ownership. Must be the owner or privileged. | 1040 | * Change file ownership. Must be the owner or privileged. |
@@ -1116,16 +1106,7 @@ xfs_ioctl_setattr( | |||
1116 | xfs_qm_dqrele(udqp); | 1106 | xfs_qm_dqrele(udqp); |
1117 | xfs_qm_dqrele(gdqp); | 1107 | xfs_qm_dqrele(gdqp); |
1118 | 1108 | ||
1119 | if (code) | 1109 | return code; |
1120 | return code; | ||
1121 | |||
1122 | if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE)) { | ||
1123 | XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, ip, DM_RIGHT_NULL, | ||
1124 | NULL, DM_RIGHT_NULL, NULL, NULL, 0, 0, | ||
1125 | (mask & FSX_NONBLOCK) ? DM_FLAGS_NDELAY : 0); | ||
1126 | } | ||
1127 | |||
1128 | return 0; | ||
1129 | 1110 | ||
1130 | error_return: | 1111 | error_return: |
1131 | xfs_qm_dqrele(udqp); | 1112 | xfs_qm_dqrele(udqp); |
@@ -1301,7 +1282,7 @@ xfs_file_ioctl( | |||
1301 | if (filp->f_mode & FMODE_NOCMTIME) | 1282 | if (filp->f_mode & FMODE_NOCMTIME) |
1302 | ioflags |= IO_INVIS; | 1283 | ioflags |= IO_INVIS; |
1303 | 1284 | ||
1304 | xfs_itrace_entry(ip); | 1285 | trace_xfs_file_ioctl(ip); |
1305 | 1286 | ||
1306 | switch (cmd) { | 1287 | switch (cmd) { |
1307 | case XFS_IOC_ALLOCSP: | 1288 | case XFS_IOC_ALLOCSP: |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 52ed49e6465c..6c83f7f62dc9 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
@@ -28,12 +28,8 @@ | |||
28 | #include "xfs_trans.h" | 28 | #include "xfs_trans.h" |
29 | #include "xfs_sb.h" | 29 | #include "xfs_sb.h" |
30 | #include "xfs_ag.h" | 30 | #include "xfs_ag.h" |
31 | #include "xfs_dir2.h" | ||
32 | #include "xfs_dmapi.h" | ||
33 | #include "xfs_mount.h" | 31 | #include "xfs_mount.h" |
34 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | ||
37 | #include "xfs_vnode.h" | 33 | #include "xfs_vnode.h" |
38 | #include "xfs_dinode.h" | 34 | #include "xfs_dinode.h" |
39 | #include "xfs_inode.h" | 35 | #include "xfs_inode.h" |
@@ -544,7 +540,7 @@ xfs_file_compat_ioctl( | |||
544 | if (filp->f_mode & FMODE_NOCMTIME) | 540 | if (filp->f_mode & FMODE_NOCMTIME) |
545 | ioflags |= IO_INVIS; | 541 | ioflags |= IO_INVIS; |
546 | 542 | ||
547 | xfs_itrace_entry(ip); | 543 | trace_xfs_file_compat_ioctl(ip); |
548 | 544 | ||
549 | switch (cmd) { | 545 | switch (cmd) { |
550 | /* No size or alignment issues on any arch */ | 546 | /* No size or alignment issues on any arch */ |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 44f0b2de153e..536b81e63a3d 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -24,21 +24,13 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_alloc.h" | 27 | #include "xfs_alloc.h" |
29 | #include "xfs_dmapi.h" | ||
30 | #include "xfs_quota.h" | 28 | #include "xfs_quota.h" |
31 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
32 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | ||
34 | #include "xfs_ialloc_btree.h" | ||
35 | #include "xfs_dir2_sf.h" | ||
36 | #include "xfs_attr_sf.h" | ||
37 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
38 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
39 | #include "xfs_bmap.h" | 33 | #include "xfs_bmap.h" |
40 | #include "xfs_btree.h" | ||
41 | #include "xfs_ialloc.h" | ||
42 | #include "xfs_rtalloc.h" | 34 | #include "xfs_rtalloc.h" |
43 | #include "xfs_error.h" | 35 | #include "xfs_error.h" |
44 | #include "xfs_itable.h" | 36 | #include "xfs_itable.h" |
@@ -496,7 +488,7 @@ xfs_vn_getattr( | |||
496 | struct xfs_inode *ip = XFS_I(inode); | 488 | struct xfs_inode *ip = XFS_I(inode); |
497 | struct xfs_mount *mp = ip->i_mount; | 489 | struct xfs_mount *mp = ip->i_mount; |
498 | 490 | ||
499 | xfs_itrace_entry(ip); | 491 | trace_xfs_getattr(ip); |
500 | 492 | ||
501 | if (XFS_FORCED_SHUTDOWN(mp)) | 493 | if (XFS_FORCED_SHUTDOWN(mp)) |
502 | return XFS_ERROR(EIO); | 494 | return XFS_ERROR(EIO); |
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index facfb323a706..998a9d7fb9c8 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h | |||
@@ -87,7 +87,6 @@ | |||
87 | #include <xfs_aops.h> | 87 | #include <xfs_aops.h> |
88 | #include <xfs_super.h> | 88 | #include <xfs_super.h> |
89 | #include <xfs_globals.h> | 89 | #include <xfs_globals.h> |
90 | #include <xfs_fs_subr.h> | ||
91 | #include <xfs_buf.h> | 90 | #include <xfs_buf.h> |
92 | 91 | ||
93 | /* | 92 | /* |
diff --git a/fs/xfs/linux-2.6/xfs_quotaops.c b/fs/xfs/linux-2.6/xfs_quotaops.c index 067cafbfc635..29b9d642e93d 100644 --- a/fs/xfs/linux-2.6/xfs_quotaops.c +++ b/fs/xfs/linux-2.6/xfs_quotaops.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include "xfs.h" | 18 | #include "xfs.h" |
19 | #include "xfs_dmapi.h" | ||
20 | #include "xfs_sb.h" | 19 | #include "xfs_sb.h" |
21 | #include "xfs_inum.h" | 20 | #include "xfs_inum.h" |
22 | #include "xfs_log.h" | 21 | #include "xfs_log.h" |
@@ -69,15 +68,15 @@ xfs_fs_set_xstate( | |||
69 | if (op != Q_XQUOTARM && !XFS_IS_QUOTA_RUNNING(mp)) | 68 | if (op != Q_XQUOTARM && !XFS_IS_QUOTA_RUNNING(mp)) |
70 | return -ENOSYS; | 69 | return -ENOSYS; |
71 | 70 | ||
72 | if (uflags & XFS_QUOTA_UDQ_ACCT) | 71 | if (uflags & FS_QUOTA_UDQ_ACCT) |
73 | flags |= XFS_UQUOTA_ACCT; | 72 | flags |= XFS_UQUOTA_ACCT; |
74 | if (uflags & XFS_QUOTA_PDQ_ACCT) | 73 | if (uflags & FS_QUOTA_PDQ_ACCT) |
75 | flags |= XFS_PQUOTA_ACCT; | 74 | flags |= XFS_PQUOTA_ACCT; |
76 | if (uflags & XFS_QUOTA_GDQ_ACCT) | 75 | if (uflags & FS_QUOTA_GDQ_ACCT) |
77 | flags |= XFS_GQUOTA_ACCT; | 76 | flags |= XFS_GQUOTA_ACCT; |
78 | if (uflags & XFS_QUOTA_UDQ_ENFD) | 77 | if (uflags & FS_QUOTA_UDQ_ENFD) |
79 | flags |= XFS_UQUOTA_ENFD; | 78 | flags |= XFS_UQUOTA_ENFD; |
80 | if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD)) | 79 | if (uflags & (FS_QUOTA_PDQ_ENFD|FS_QUOTA_GDQ_ENFD)) |
81 | flags |= XFS_OQUOTA_ENFD; | 80 | flags |= XFS_OQUOTA_ENFD; |
82 | 81 | ||
83 | switch (op) { | 82 | switch (op) { |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index f2d1718c9165..758df94690ed 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -25,14 +25,11 @@ | |||
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
27 | #include "xfs_alloc.h" | 27 | #include "xfs_alloc.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_quota.h" | 28 | #include "xfs_quota.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | 33 | #include "xfs_dinode.h" |
37 | #include "xfs_inode.h" | 34 | #include "xfs_inode.h" |
38 | #include "xfs_btree.h" | 35 | #include "xfs_btree.h" |
@@ -43,7 +40,6 @@ | |||
43 | #include "xfs_error.h" | 40 | #include "xfs_error.h" |
44 | #include "xfs_itable.h" | 41 | #include "xfs_itable.h" |
45 | #include "xfs_fsops.h" | 42 | #include "xfs_fsops.h" |
46 | #include "xfs_rw.h" | ||
47 | #include "xfs_attr.h" | 43 | #include "xfs_attr.h" |
48 | #include "xfs_buf_item.h" | 44 | #include "xfs_buf_item.h" |
49 | #include "xfs_utils.h" | 45 | #include "xfs_utils.h" |
@@ -94,7 +90,6 @@ mempool_t *xfs_ioend_pool; | |||
94 | #define MNTOPT_BARRIER "barrier" /* use writer barriers for log write and | 90 | #define MNTOPT_BARRIER "barrier" /* use writer barriers for log write and |
95 | * unwritten extent conversion */ | 91 | * unwritten extent conversion */ |
96 | #define MNTOPT_NOBARRIER "nobarrier" /* .. disable */ | 92 | #define MNTOPT_NOBARRIER "nobarrier" /* .. disable */ |
97 | #define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */ | ||
98 | #define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */ | 93 | #define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */ |
99 | #define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */ | 94 | #define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */ |
100 | #define MNTOPT_NOIKEEP "noikeep" /* free empty inode clusters */ | 95 | #define MNTOPT_NOIKEEP "noikeep" /* free empty inode clusters */ |
@@ -116,9 +111,6 @@ mempool_t *xfs_ioend_pool; | |||
116 | #define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */ | 111 | #define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */ |
117 | #define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */ | 112 | #define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */ |
118 | #define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */ | 113 | #define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */ |
119 | #define MNTOPT_DMAPI "dmapi" /* DMI enabled (DMAPI / XDSM) */ | ||
120 | #define MNTOPT_XDSM "xdsm" /* DMI enabled (DMAPI / XDSM) */ | ||
121 | #define MNTOPT_DMI "dmi" /* DMI enabled (DMAPI / XDSM) */ | ||
122 | #define MNTOPT_DELAYLOG "delaylog" /* Delayed loging enabled */ | 114 | #define MNTOPT_DELAYLOG "delaylog" /* Delayed loging enabled */ |
123 | #define MNTOPT_NODELAYLOG "nodelaylog" /* Delayed loging disabled */ | 115 | #define MNTOPT_NODELAYLOG "nodelaylog" /* Delayed loging disabled */ |
124 | 116 | ||
@@ -172,15 +164,13 @@ suffix_strtoul(char *s, char **endp, unsigned int base) | |||
172 | STATIC int | 164 | STATIC int |
173 | xfs_parseargs( | 165 | xfs_parseargs( |
174 | struct xfs_mount *mp, | 166 | struct xfs_mount *mp, |
175 | char *options, | 167 | char *options) |
176 | char **mtpt) | ||
177 | { | 168 | { |
178 | struct super_block *sb = mp->m_super; | 169 | struct super_block *sb = mp->m_super; |
179 | char *this_char, *value, *eov; | 170 | char *this_char, *value, *eov; |
180 | int dsunit = 0; | 171 | int dsunit = 0; |
181 | int dswidth = 0; | 172 | int dswidth = 0; |
182 | int iosize = 0; | 173 | int iosize = 0; |
183 | int dmapi_implies_ikeep = 1; | ||
184 | __uint8_t iosizelog = 0; | 174 | __uint8_t iosizelog = 0; |
185 | 175 | ||
186 | /* | 176 | /* |
@@ -243,15 +233,10 @@ xfs_parseargs( | |||
243 | if (!mp->m_logname) | 233 | if (!mp->m_logname) |
244 | return ENOMEM; | 234 | return ENOMEM; |
245 | } else if (!strcmp(this_char, MNTOPT_MTPT)) { | 235 | } else if (!strcmp(this_char, MNTOPT_MTPT)) { |
246 | if (!value || !*value) { | 236 | cmn_err(CE_WARN, |
247 | cmn_err(CE_WARN, | 237 | "XFS: %s option not allowed on this system", |
248 | "XFS: %s option requires an argument", | 238 | this_char); |
249 | this_char); | 239 | return EINVAL; |
250 | return EINVAL; | ||
251 | } | ||
252 | *mtpt = kstrndup(value, MAXNAMELEN, GFP_KERNEL); | ||
253 | if (!*mtpt) | ||
254 | return ENOMEM; | ||
255 | } else if (!strcmp(this_char, MNTOPT_RTDEV)) { | 240 | } else if (!strcmp(this_char, MNTOPT_RTDEV)) { |
256 | if (!value || !*value) { | 241 | if (!value || !*value) { |
257 | cmn_err(CE_WARN, | 242 | cmn_err(CE_WARN, |
@@ -288,8 +273,6 @@ xfs_parseargs( | |||
288 | mp->m_flags &= ~XFS_MOUNT_GRPID; | 273 | mp->m_flags &= ~XFS_MOUNT_GRPID; |
289 | } else if (!strcmp(this_char, MNTOPT_WSYNC)) { | 274 | } else if (!strcmp(this_char, MNTOPT_WSYNC)) { |
290 | mp->m_flags |= XFS_MOUNT_WSYNC; | 275 | mp->m_flags |= XFS_MOUNT_WSYNC; |
291 | } else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) { | ||
292 | mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC; | ||
293 | } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) { | 276 | } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) { |
294 | mp->m_flags |= XFS_MOUNT_NORECOVERY; | 277 | mp->m_flags |= XFS_MOUNT_NORECOVERY; |
295 | } else if (!strcmp(this_char, MNTOPT_NOALIGN)) { | 278 | } else if (!strcmp(this_char, MNTOPT_NOALIGN)) { |
@@ -329,7 +312,6 @@ xfs_parseargs( | |||
329 | } else if (!strcmp(this_char, MNTOPT_IKEEP)) { | 312 | } else if (!strcmp(this_char, MNTOPT_IKEEP)) { |
330 | mp->m_flags |= XFS_MOUNT_IKEEP; | 313 | mp->m_flags |= XFS_MOUNT_IKEEP; |
331 | } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) { | 314 | } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) { |
332 | dmapi_implies_ikeep = 0; | ||
333 | mp->m_flags &= ~XFS_MOUNT_IKEEP; | 315 | mp->m_flags &= ~XFS_MOUNT_IKEEP; |
334 | } else if (!strcmp(this_char, MNTOPT_LARGEIO)) { | 316 | } else if (!strcmp(this_char, MNTOPT_LARGEIO)) { |
335 | mp->m_flags &= ~XFS_MOUNT_COMPAT_IOSIZE; | 317 | mp->m_flags &= ~XFS_MOUNT_COMPAT_IOSIZE; |
@@ -370,12 +352,6 @@ xfs_parseargs( | |||
370 | } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) { | 352 | } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) { |
371 | mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE); | 353 | mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE); |
372 | mp->m_qflags &= ~XFS_OQUOTA_ENFD; | 354 | mp->m_qflags &= ~XFS_OQUOTA_ENFD; |
373 | } else if (!strcmp(this_char, MNTOPT_DMAPI)) { | ||
374 | mp->m_flags |= XFS_MOUNT_DMAPI; | ||
375 | } else if (!strcmp(this_char, MNTOPT_XDSM)) { | ||
376 | mp->m_flags |= XFS_MOUNT_DMAPI; | ||
377 | } else if (!strcmp(this_char, MNTOPT_DMI)) { | ||
378 | mp->m_flags |= XFS_MOUNT_DMAPI; | ||
379 | } else if (!strcmp(this_char, MNTOPT_DELAYLOG)) { | 355 | } else if (!strcmp(this_char, MNTOPT_DELAYLOG)) { |
380 | mp->m_flags |= XFS_MOUNT_DELAYLOG; | 356 | mp->m_flags |= XFS_MOUNT_DELAYLOG; |
381 | cmn_err(CE_WARN, | 357 | cmn_err(CE_WARN, |
@@ -387,9 +363,11 @@ xfs_parseargs( | |||
387 | cmn_err(CE_WARN, | 363 | cmn_err(CE_WARN, |
388 | "XFS: ihashsize no longer used, option is deprecated."); | 364 | "XFS: ihashsize no longer used, option is deprecated."); |
389 | } else if (!strcmp(this_char, "osyncisdsync")) { | 365 | } else if (!strcmp(this_char, "osyncisdsync")) { |
390 | /* no-op, this is now the default */ | ||
391 | cmn_err(CE_WARN, | 366 | cmn_err(CE_WARN, |
392 | "XFS: osyncisdsync is now the default, option is deprecated."); | 367 | "XFS: osyncisdsync has no effect, option is deprecated."); |
368 | } else if (!strcmp(this_char, "osyncisosync")) { | ||
369 | cmn_err(CE_WARN, | ||
370 | "XFS: osyncisosync has no effect, option is deprecated."); | ||
393 | } else if (!strcmp(this_char, "irixsgid")) { | 371 | } else if (!strcmp(this_char, "irixsgid")) { |
394 | cmn_err(CE_WARN, | 372 | cmn_err(CE_WARN, |
395 | "XFS: irixsgid is now a sysctl(2) variable, option is deprecated."); | 373 | "XFS: irixsgid is now a sysctl(2) variable, option is deprecated."); |
@@ -430,12 +408,6 @@ xfs_parseargs( | |||
430 | return EINVAL; | 408 | return EINVAL; |
431 | } | 409 | } |
432 | 410 | ||
433 | if ((mp->m_flags & XFS_MOUNT_DMAPI) && (!*mtpt || *mtpt[0] == '\0')) { | ||
434 | printk("XFS: %s option needs the mount point option as well\n", | ||
435 | MNTOPT_DMAPI); | ||
436 | return EINVAL; | ||
437 | } | ||
438 | |||
439 | if ((dsunit && !dswidth) || (!dsunit && dswidth)) { | 411 | if ((dsunit && !dswidth) || (!dsunit && dswidth)) { |
440 | cmn_err(CE_WARN, | 412 | cmn_err(CE_WARN, |
441 | "XFS: sunit and swidth must be specified together"); | 413 | "XFS: sunit and swidth must be specified together"); |
@@ -449,18 +421,6 @@ xfs_parseargs( | |||
449 | return EINVAL; | 421 | return EINVAL; |
450 | } | 422 | } |
451 | 423 | ||
452 | /* | ||
453 | * Applications using DMI filesystems often expect the | ||
454 | * inode generation number to be monotonically increasing. | ||
455 | * If we delete inode chunks we break this assumption, so | ||
456 | * keep unused inode chunks on disk for DMI filesystems | ||
457 | * until we come up with a better solution. | ||
458 | * Note that if "ikeep" or "noikeep" mount options are | ||
459 | * supplied, then they are honored. | ||
460 | */ | ||
461 | if ((mp->m_flags & XFS_MOUNT_DMAPI) && dmapi_implies_ikeep) | ||
462 | mp->m_flags |= XFS_MOUNT_IKEEP; | ||
463 | |||
464 | done: | 424 | done: |
465 | if (!(mp->m_flags & XFS_MOUNT_NOALIGN)) { | 425 | if (!(mp->m_flags & XFS_MOUNT_NOALIGN)) { |
466 | /* | 426 | /* |
@@ -539,10 +499,8 @@ xfs_showargs( | |||
539 | { XFS_MOUNT_SWALLOC, "," MNTOPT_SWALLOC }, | 499 | { XFS_MOUNT_SWALLOC, "," MNTOPT_SWALLOC }, |
540 | { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID }, | 500 | { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID }, |
541 | { XFS_MOUNT_NORECOVERY, "," MNTOPT_NORECOVERY }, | 501 | { XFS_MOUNT_NORECOVERY, "," MNTOPT_NORECOVERY }, |
542 | { XFS_MOUNT_OSYNCISOSYNC, "," MNTOPT_OSYNCISOSYNC }, | ||
543 | { XFS_MOUNT_ATTR2, "," MNTOPT_ATTR2 }, | 502 | { XFS_MOUNT_ATTR2, "," MNTOPT_ATTR2 }, |
544 | { XFS_MOUNT_FILESTREAMS, "," MNTOPT_FILESTREAM }, | 503 | { XFS_MOUNT_FILESTREAMS, "," MNTOPT_FILESTREAM }, |
545 | { XFS_MOUNT_DMAPI, "," MNTOPT_DMAPI }, | ||
546 | { XFS_MOUNT_GRPID, "," MNTOPT_GRPID }, | 504 | { XFS_MOUNT_GRPID, "," MNTOPT_GRPID }, |
547 | { XFS_MOUNT_DELAYLOG, "," MNTOPT_DELAYLOG }, | 505 | { XFS_MOUNT_DELAYLOG, "," MNTOPT_DELAYLOG }, |
548 | { 0, NULL } | 506 | { 0, NULL } |
@@ -947,7 +905,7 @@ xfs_fs_destroy_inode( | |||
947 | { | 905 | { |
948 | struct xfs_inode *ip = XFS_I(inode); | 906 | struct xfs_inode *ip = XFS_I(inode); |
949 | 907 | ||
950 | xfs_itrace_entry(ip); | 908 | trace_xfs_destroy_inode(ip); |
951 | 909 | ||
952 | XFS_STATS_INC(vn_reclaim); | 910 | XFS_STATS_INC(vn_reclaim); |
953 | 911 | ||
@@ -1063,10 +1021,8 @@ xfs_log_inode( | |||
1063 | * an inode in another recent transaction. So we play it safe and | 1021 | * an inode in another recent transaction. So we play it safe and |
1064 | * fire off the transaction anyway. | 1022 | * fire off the transaction anyway. |
1065 | */ | 1023 | */ |
1066 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 1024 | xfs_trans_ijoin(tp, ip); |
1067 | xfs_trans_ihold(tp, ip); | ||
1068 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 1025 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
1069 | xfs_trans_set_sync(tp); | ||
1070 | error = xfs_trans_commit(tp, 0); | 1026 | error = xfs_trans_commit(tp, 0); |
1071 | xfs_ilock_demote(ip, XFS_ILOCK_EXCL); | 1027 | xfs_ilock_demote(ip, XFS_ILOCK_EXCL); |
1072 | 1028 | ||
@@ -1082,27 +1038,18 @@ xfs_fs_write_inode( | |||
1082 | struct xfs_mount *mp = ip->i_mount; | 1038 | struct xfs_mount *mp = ip->i_mount; |
1083 | int error = EAGAIN; | 1039 | int error = EAGAIN; |
1084 | 1040 | ||
1085 | xfs_itrace_entry(ip); | 1041 | trace_xfs_write_inode(ip); |
1086 | 1042 | ||
1087 | if (XFS_FORCED_SHUTDOWN(mp)) | 1043 | if (XFS_FORCED_SHUTDOWN(mp)) |
1088 | return XFS_ERROR(EIO); | 1044 | return XFS_ERROR(EIO); |
1089 | 1045 | ||
1090 | if (wbc->sync_mode == WB_SYNC_ALL) { | 1046 | if (wbc->sync_mode == WB_SYNC_ALL) { |
1091 | /* | 1047 | /* |
1092 | * Make sure the inode has hit stable storage. By using the | 1048 | * Make sure the inode has made it it into the log. Instead |
1093 | * log and the fsync transactions we reduce the IOs we have | 1049 | * of forcing it all the way to stable storage using a |
1094 | * to do here from two (log and inode) to just the log. | 1050 | * synchronous transaction we let the log force inside the |
1095 | * | 1051 | * ->sync_fs call do that for thus, which reduces the number |
1096 | * Note: We still need to do a delwri write of the inode after | 1052 | * of synchronous log foces dramatically. |
1097 | * this to flush it to the backing buffer so that bulkstat | ||
1098 | * works properly if this is the first time the inode has been | ||
1099 | * written. Because we hold the ilock atomically over the | ||
1100 | * transaction commit and the inode flush we are guaranteed | ||
1101 | * that the inode is not pinned when it returns. If the flush | ||
1102 | * lock is already held, then the inode has already been | ||
1103 | * flushed once and we don't need to flush it again. Hence | ||
1104 | * the code will only flush the inode if it isn't already | ||
1105 | * being flushed. | ||
1106 | */ | 1053 | */ |
1107 | xfs_ioend_wait(ip); | 1054 | xfs_ioend_wait(ip); |
1108 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 1055 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
@@ -1116,27 +1063,29 @@ xfs_fs_write_inode( | |||
1116 | * We make this non-blocking if the inode is contended, return | 1063 | * We make this non-blocking if the inode is contended, return |
1117 | * EAGAIN to indicate to the caller that they did not succeed. | 1064 | * EAGAIN to indicate to the caller that they did not succeed. |
1118 | * This prevents the flush path from blocking on inodes inside | 1065 | * This prevents the flush path from blocking on inodes inside |
1119 | * another operation right now, they get caught later by xfs_sync. | 1066 | * another operation right now, they get caught later by |
1067 | * xfs_sync. | ||
1120 | */ | 1068 | */ |
1121 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) | 1069 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) |
1122 | goto out; | 1070 | goto out; |
1123 | } | ||
1124 | 1071 | ||
1125 | if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) | 1072 | if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) |
1126 | goto out_unlock; | 1073 | goto out_unlock; |
1127 | 1074 | ||
1128 | /* | 1075 | /* |
1129 | * Now we have the flush lock and the inode is not pinned, we can check | 1076 | * Now we have the flush lock and the inode is not pinned, we |
1130 | * if the inode is really clean as we know that there are no pending | 1077 | * can check if the inode is really clean as we know that |
1131 | * transaction completions, it is not waiting on the delayed write | 1078 | * there are no pending transaction completions, it is not |
1132 | * queue and there is no IO in progress. | 1079 | * waiting on the delayed write queue and there is no IO in |
1133 | */ | 1080 | * progress. |
1134 | if (xfs_inode_clean(ip)) { | 1081 | */ |
1135 | xfs_ifunlock(ip); | 1082 | if (xfs_inode_clean(ip)) { |
1136 | error = 0; | 1083 | xfs_ifunlock(ip); |
1137 | goto out_unlock; | 1084 | error = 0; |
1085 | goto out_unlock; | ||
1086 | } | ||
1087 | error = xfs_iflush(ip, 0); | ||
1138 | } | 1088 | } |
1139 | error = xfs_iflush(ip, 0); | ||
1140 | 1089 | ||
1141 | out_unlock: | 1090 | out_unlock: |
1142 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 1091 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
@@ -1156,7 +1105,8 @@ xfs_fs_clear_inode( | |||
1156 | { | 1105 | { |
1157 | xfs_inode_t *ip = XFS_I(inode); | 1106 | xfs_inode_t *ip = XFS_I(inode); |
1158 | 1107 | ||
1159 | xfs_itrace_entry(ip); | 1108 | trace_xfs_clear_inode(ip); |
1109 | |||
1160 | XFS_STATS_INC(vn_rele); | 1110 | XFS_STATS_INC(vn_rele); |
1161 | XFS_STATS_INC(vn_remove); | 1111 | XFS_STATS_INC(vn_remove); |
1162 | XFS_STATS_DEC(vn_active); | 1112 | XFS_STATS_DEC(vn_active); |
@@ -1193,22 +1143,13 @@ xfs_fs_put_super( | |||
1193 | { | 1143 | { |
1194 | struct xfs_mount *mp = XFS_M(sb); | 1144 | struct xfs_mount *mp = XFS_M(sb); |
1195 | 1145 | ||
1146 | /* | ||
1147 | * Unregister the memory shrinker before we tear down the mount | ||
1148 | * structure so we don't have memory reclaim racing with us here. | ||
1149 | */ | ||
1150 | xfs_inode_shrinker_unregister(mp); | ||
1196 | xfs_syncd_stop(mp); | 1151 | xfs_syncd_stop(mp); |
1197 | 1152 | ||
1198 | if (!(sb->s_flags & MS_RDONLY)) { | ||
1199 | /* | ||
1200 | * XXX(hch): this should be SYNC_WAIT. | ||
1201 | * | ||
1202 | * Or more likely not needed at all because the VFS is already | ||
1203 | * calling ->sync_fs after shutting down all filestem | ||
1204 | * operations and just before calling ->put_super. | ||
1205 | */ | ||
1206 | xfs_sync_data(mp, 0); | ||
1207 | xfs_sync_attr(mp, 0); | ||
1208 | } | ||
1209 | |||
1210 | XFS_SEND_PREUNMOUNT(mp); | ||
1211 | |||
1212 | /* | 1153 | /* |
1213 | * Blow away any referenced inode in the filestreams cache. | 1154 | * Blow away any referenced inode in the filestreams cache. |
1214 | * This can and will cause log traffic as inodes go inactive | 1155 | * This can and will cause log traffic as inodes go inactive |
@@ -1218,14 +1159,10 @@ xfs_fs_put_super( | |||
1218 | 1159 | ||
1219 | XFS_bflush(mp->m_ddev_targp); | 1160 | XFS_bflush(mp->m_ddev_targp); |
1220 | 1161 | ||
1221 | XFS_SEND_UNMOUNT(mp); | ||
1222 | |||
1223 | xfs_unmountfs(mp); | 1162 | xfs_unmountfs(mp); |
1224 | xfs_freesb(mp); | 1163 | xfs_freesb(mp); |
1225 | xfs_inode_shrinker_unregister(mp); | ||
1226 | xfs_icsb_destroy_counters(mp); | 1164 | xfs_icsb_destroy_counters(mp); |
1227 | xfs_close_devices(mp); | 1165 | xfs_close_devices(mp); |
1228 | xfs_dmops_put(mp); | ||
1229 | xfs_free_fsname(mp); | 1166 | xfs_free_fsname(mp); |
1230 | kfree(mp); | 1167 | kfree(mp); |
1231 | } | 1168 | } |
@@ -1543,7 +1480,6 @@ xfs_fs_fill_super( | |||
1543 | struct inode *root; | 1480 | struct inode *root; |
1544 | struct xfs_mount *mp = NULL; | 1481 | struct xfs_mount *mp = NULL; |
1545 | int flags = 0, error = ENOMEM; | 1482 | int flags = 0, error = ENOMEM; |
1546 | char *mtpt = NULL; | ||
1547 | 1483 | ||
1548 | mp = kzalloc(sizeof(struct xfs_mount), GFP_KERNEL); | 1484 | mp = kzalloc(sizeof(struct xfs_mount), GFP_KERNEL); |
1549 | if (!mp) | 1485 | if (!mp) |
@@ -1559,7 +1495,7 @@ xfs_fs_fill_super( | |||
1559 | mp->m_super = sb; | 1495 | mp->m_super = sb; |
1560 | sb->s_fs_info = mp; | 1496 | sb->s_fs_info = mp; |
1561 | 1497 | ||
1562 | error = xfs_parseargs(mp, (char *)data, &mtpt); | 1498 | error = xfs_parseargs(mp, (char *)data); |
1563 | if (error) | 1499 | if (error) |
1564 | goto out_free_fsname; | 1500 | goto out_free_fsname; |
1565 | 1501 | ||
@@ -1571,16 +1507,12 @@ xfs_fs_fill_super( | |||
1571 | #endif | 1507 | #endif |
1572 | sb->s_op = &xfs_super_operations; | 1508 | sb->s_op = &xfs_super_operations; |
1573 | 1509 | ||
1574 | error = xfs_dmops_get(mp); | ||
1575 | if (error) | ||
1576 | goto out_free_fsname; | ||
1577 | |||
1578 | if (silent) | 1510 | if (silent) |
1579 | flags |= XFS_MFSI_QUIET; | 1511 | flags |= XFS_MFSI_QUIET; |
1580 | 1512 | ||
1581 | error = xfs_open_devices(mp); | 1513 | error = xfs_open_devices(mp); |
1582 | if (error) | 1514 | if (error) |
1583 | goto out_put_dmops; | 1515 | goto out_free_fsname; |
1584 | 1516 | ||
1585 | if (xfs_icsb_init_counters(mp)) | 1517 | if (xfs_icsb_init_counters(mp)) |
1586 | mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB; | 1518 | mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB; |
@@ -1608,8 +1540,6 @@ xfs_fs_fill_super( | |||
1608 | if (error) | 1540 | if (error) |
1609 | goto out_filestream_unmount; | 1541 | goto out_filestream_unmount; |
1610 | 1542 | ||
1611 | XFS_SEND_MOUNT(mp, DM_RIGHT_NULL, mtpt, mp->m_fsname); | ||
1612 | |||
1613 | sb->s_magic = XFS_SB_MAGIC; | 1543 | sb->s_magic = XFS_SB_MAGIC; |
1614 | sb->s_blocksize = mp->m_sb.sb_blocksize; | 1544 | sb->s_blocksize = mp->m_sb.sb_blocksize; |
1615 | sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1; | 1545 | sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1; |
@@ -1638,7 +1568,6 @@ xfs_fs_fill_super( | |||
1638 | 1568 | ||
1639 | xfs_inode_shrinker_register(mp); | 1569 | xfs_inode_shrinker_register(mp); |
1640 | 1570 | ||
1641 | kfree(mtpt); | ||
1642 | return 0; | 1571 | return 0; |
1643 | 1572 | ||
1644 | out_filestream_unmount: | 1573 | out_filestream_unmount: |
@@ -1648,11 +1577,8 @@ xfs_fs_fill_super( | |||
1648 | out_destroy_counters: | 1577 | out_destroy_counters: |
1649 | xfs_icsb_destroy_counters(mp); | 1578 | xfs_icsb_destroy_counters(mp); |
1650 | xfs_close_devices(mp); | 1579 | xfs_close_devices(mp); |
1651 | out_put_dmops: | ||
1652 | xfs_dmops_put(mp); | ||
1653 | out_free_fsname: | 1580 | out_free_fsname: |
1654 | xfs_free_fsname(mp); | 1581 | xfs_free_fsname(mp); |
1655 | kfree(mtpt); | ||
1656 | kfree(mp); | 1582 | kfree(mp); |
1657 | out: | 1583 | out: |
1658 | return -error; | 1584 | return -error; |
@@ -1759,6 +1685,12 @@ xfs_init_zones(void) | |||
1759 | if (!xfs_trans_zone) | 1685 | if (!xfs_trans_zone) |
1760 | goto out_destroy_ifork_zone; | 1686 | goto out_destroy_ifork_zone; |
1761 | 1687 | ||
1688 | xfs_log_item_desc_zone = | ||
1689 | kmem_zone_init(sizeof(struct xfs_log_item_desc), | ||
1690 | "xfs_log_item_desc"); | ||
1691 | if (!xfs_log_item_desc_zone) | ||
1692 | goto out_destroy_trans_zone; | ||
1693 | |||
1762 | /* | 1694 | /* |
1763 | * The size of the zone allocated buf log item is the maximum | 1695 | * The size of the zone allocated buf log item is the maximum |
1764 | * size possible under XFS. This wastes a little bit of memory, | 1696 | * size possible under XFS. This wastes a little bit of memory, |
@@ -1768,7 +1700,7 @@ xfs_init_zones(void) | |||
1768 | (((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) / | 1700 | (((XFS_MAX_BLOCKSIZE / XFS_BLF_CHUNK) / |
1769 | NBWORD) * sizeof(int))), "xfs_buf_item"); | 1701 | NBWORD) * sizeof(int))), "xfs_buf_item"); |
1770 | if (!xfs_buf_item_zone) | 1702 | if (!xfs_buf_item_zone) |
1771 | goto out_destroy_trans_zone; | 1703 | goto out_destroy_log_item_desc_zone; |
1772 | 1704 | ||
1773 | xfs_efd_zone = kmem_zone_init((sizeof(xfs_efd_log_item_t) + | 1705 | xfs_efd_zone = kmem_zone_init((sizeof(xfs_efd_log_item_t) + |
1774 | ((XFS_EFD_MAX_FAST_EXTENTS - 1) * | 1706 | ((XFS_EFD_MAX_FAST_EXTENTS - 1) * |
@@ -1805,6 +1737,8 @@ xfs_init_zones(void) | |||
1805 | kmem_zone_destroy(xfs_efd_zone); | 1737 | kmem_zone_destroy(xfs_efd_zone); |
1806 | out_destroy_buf_item_zone: | 1738 | out_destroy_buf_item_zone: |
1807 | kmem_zone_destroy(xfs_buf_item_zone); | 1739 | kmem_zone_destroy(xfs_buf_item_zone); |
1740 | out_destroy_log_item_desc_zone: | ||
1741 | kmem_zone_destroy(xfs_log_item_desc_zone); | ||
1808 | out_destroy_trans_zone: | 1742 | out_destroy_trans_zone: |
1809 | kmem_zone_destroy(xfs_trans_zone); | 1743 | kmem_zone_destroy(xfs_trans_zone); |
1810 | out_destroy_ifork_zone: | 1744 | out_destroy_ifork_zone: |
@@ -1835,6 +1769,7 @@ xfs_destroy_zones(void) | |||
1835 | kmem_zone_destroy(xfs_efi_zone); | 1769 | kmem_zone_destroy(xfs_efi_zone); |
1836 | kmem_zone_destroy(xfs_efd_zone); | 1770 | kmem_zone_destroy(xfs_efd_zone); |
1837 | kmem_zone_destroy(xfs_buf_item_zone); | 1771 | kmem_zone_destroy(xfs_buf_item_zone); |
1772 | kmem_zone_destroy(xfs_log_item_desc_zone); | ||
1838 | kmem_zone_destroy(xfs_trans_zone); | 1773 | kmem_zone_destroy(xfs_trans_zone); |
1839 | kmem_zone_destroy(xfs_ifork_zone); | 1774 | kmem_zone_destroy(xfs_ifork_zone); |
1840 | kmem_zone_destroy(xfs_dabuf_zone); | 1775 | kmem_zone_destroy(xfs_dabuf_zone); |
@@ -1883,7 +1818,6 @@ init_xfs_fs(void) | |||
1883 | goto out_cleanup_procfs; | 1818 | goto out_cleanup_procfs; |
1884 | 1819 | ||
1885 | vfs_initquota(); | 1820 | vfs_initquota(); |
1886 | xfs_inode_shrinker_init(); | ||
1887 | 1821 | ||
1888 | error = register_filesystem(&xfs_fs_type); | 1822 | error = register_filesystem(&xfs_fs_type); |
1889 | if (error) | 1823 | if (error) |
@@ -1911,7 +1845,6 @@ exit_xfs_fs(void) | |||
1911 | { | 1845 | { |
1912 | vfs_exitquota(); | 1846 | vfs_exitquota(); |
1913 | unregister_filesystem(&xfs_fs_type); | 1847 | unregister_filesystem(&xfs_fs_type); |
1914 | xfs_inode_shrinker_destroy(); | ||
1915 | xfs_sysctl_unregister(); | 1848 | xfs_sysctl_unregister(); |
1916 | xfs_cleanup_procfs(); | 1849 | xfs_cleanup_procfs(); |
1917 | xfs_buf_terminate(); | 1850 | xfs_buf_terminate(); |
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index 519618e9279e..1ef4a4d2d997 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h | |||
@@ -56,12 +56,6 @@ extern void xfs_qm_exit(void); | |||
56 | # define XFS_BIGFS_STRING | 56 | # define XFS_BIGFS_STRING |
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | #ifdef CONFIG_XFS_DMAPI | ||
60 | # define XFS_DMAPI_STRING "dmapi support, " | ||
61 | #else | ||
62 | # define XFS_DMAPI_STRING | ||
63 | #endif | ||
64 | |||
65 | #ifdef DEBUG | 59 | #ifdef DEBUG |
66 | # define XFS_DBG_STRING "debug" | 60 | # define XFS_DBG_STRING "debug" |
67 | #else | 61 | #else |
@@ -72,7 +66,6 @@ extern void xfs_qm_exit(void); | |||
72 | XFS_SECURITY_STRING \ | 66 | XFS_SECURITY_STRING \ |
73 | XFS_REALTIME_STRING \ | 67 | XFS_REALTIME_STRING \ |
74 | XFS_BIGFS_STRING \ | 68 | XFS_BIGFS_STRING \ |
75 | XFS_DMAPI_STRING \ | ||
76 | XFS_DBG_STRING /* DBG must be last */ | 69 | XFS_DBG_STRING /* DBG must be last */ |
77 | 70 | ||
78 | struct xfs_inode; | 71 | struct xfs_inode; |
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c index ef7f0218bccb..dfcbd98d1599 100644 --- a/fs/xfs/linux-2.6/xfs_sync.c +++ b/fs/xfs/linux-2.6/xfs_sync.c | |||
@@ -24,25 +24,14 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | ||
32 | #include "xfs_ialloc_btree.h" | ||
33 | #include "xfs_btree.h" | ||
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_inode.h" | 29 | #include "xfs_inode.h" |
37 | #include "xfs_dinode.h" | 30 | #include "xfs_dinode.h" |
38 | #include "xfs_error.h" | 31 | #include "xfs_error.h" |
39 | #include "xfs_mru_cache.h" | ||
40 | #include "xfs_filestream.h" | 32 | #include "xfs_filestream.h" |
41 | #include "xfs_vnodeops.h" | 33 | #include "xfs_vnodeops.h" |
42 | #include "xfs_utils.h" | ||
43 | #include "xfs_buf_item.h" | ||
44 | #include "xfs_inode_item.h" | 34 | #include "xfs_inode_item.h" |
45 | #include "xfs_rw.h" | ||
46 | #include "xfs_quota.h" | 35 | #include "xfs_quota.h" |
47 | #include "xfs_trace.h" | 36 | #include "xfs_trace.h" |
48 | 37 | ||
@@ -144,6 +133,41 @@ restart: | |||
144 | return last_error; | 133 | return last_error; |
145 | } | 134 | } |
146 | 135 | ||
136 | /* | ||
137 | * Select the next per-ag structure to iterate during the walk. The reclaim | ||
138 | * walk is optimised only to walk AGs with reclaimable inodes in them. | ||
139 | */ | ||
140 | static struct xfs_perag * | ||
141 | xfs_inode_ag_iter_next_pag( | ||
142 | struct xfs_mount *mp, | ||
143 | xfs_agnumber_t *first, | ||
144 | int tag) | ||
145 | { | ||
146 | struct xfs_perag *pag = NULL; | ||
147 | |||
148 | if (tag == XFS_ICI_RECLAIM_TAG) { | ||
149 | int found; | ||
150 | int ref; | ||
151 | |||
152 | spin_lock(&mp->m_perag_lock); | ||
153 | found = radix_tree_gang_lookup_tag(&mp->m_perag_tree, | ||
154 | (void **)&pag, *first, 1, tag); | ||
155 | if (found <= 0) { | ||
156 | spin_unlock(&mp->m_perag_lock); | ||
157 | return NULL; | ||
158 | } | ||
159 | *first = pag->pag_agno + 1; | ||
160 | /* open coded pag reference increment */ | ||
161 | ref = atomic_inc_return(&pag->pag_ref); | ||
162 | spin_unlock(&mp->m_perag_lock); | ||
163 | trace_xfs_perag_get_reclaim(mp, pag->pag_agno, ref, _RET_IP_); | ||
164 | } else { | ||
165 | pag = xfs_perag_get(mp, *first); | ||
166 | (*first)++; | ||
167 | } | ||
168 | return pag; | ||
169 | } | ||
170 | |||
147 | int | 171 | int |
148 | xfs_inode_ag_iterator( | 172 | xfs_inode_ag_iterator( |
149 | struct xfs_mount *mp, | 173 | struct xfs_mount *mp, |
@@ -154,16 +178,15 @@ xfs_inode_ag_iterator( | |||
154 | int exclusive, | 178 | int exclusive, |
155 | int *nr_to_scan) | 179 | int *nr_to_scan) |
156 | { | 180 | { |
181 | struct xfs_perag *pag; | ||
157 | int error = 0; | 182 | int error = 0; |
158 | int last_error = 0; | 183 | int last_error = 0; |
159 | xfs_agnumber_t ag; | 184 | xfs_agnumber_t ag; |
160 | int nr; | 185 | int nr; |
161 | 186 | ||
162 | nr = nr_to_scan ? *nr_to_scan : INT_MAX; | 187 | nr = nr_to_scan ? *nr_to_scan : INT_MAX; |
163 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { | 188 | ag = 0; |
164 | struct xfs_perag *pag; | 189 | while ((pag = xfs_inode_ag_iter_next_pag(mp, &ag, tag))) { |
165 | |||
166 | pag = xfs_perag_get(mp, ag); | ||
167 | error = xfs_inode_ag_walk(mp, pag, execute, flags, tag, | 190 | error = xfs_inode_ag_walk(mp, pag, execute, flags, tag, |
168 | exclusive, &nr); | 191 | exclusive, &nr); |
169 | xfs_perag_put(pag); | 192 | xfs_perag_put(pag); |
@@ -285,7 +308,7 @@ xfs_sync_inode_attr( | |||
285 | /* | 308 | /* |
286 | * Write out pagecache data for the whole filesystem. | 309 | * Write out pagecache data for the whole filesystem. |
287 | */ | 310 | */ |
288 | int | 311 | STATIC int |
289 | xfs_sync_data( | 312 | xfs_sync_data( |
290 | struct xfs_mount *mp, | 313 | struct xfs_mount *mp, |
291 | int flags) | 314 | int flags) |
@@ -306,7 +329,7 @@ xfs_sync_data( | |||
306 | /* | 329 | /* |
307 | * Write out inode metadata (attributes) for the whole filesystem. | 330 | * Write out inode metadata (attributes) for the whole filesystem. |
308 | */ | 331 | */ |
309 | int | 332 | STATIC int |
310 | xfs_sync_attr( | 333 | xfs_sync_attr( |
311 | struct xfs_mount *mp, | 334 | struct xfs_mount *mp, |
312 | int flags) | 335 | int flags) |
@@ -339,8 +362,7 @@ xfs_commit_dummy_trans( | |||
339 | 362 | ||
340 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 363 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
341 | 364 | ||
342 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 365 | xfs_trans_ijoin(tp, ip); |
343 | xfs_trans_ihold(tp, ip); | ||
344 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 366 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
345 | error = xfs_trans_commit(tp, 0); | 367 | error = xfs_trans_commit(tp, 0); |
346 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 368 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
@@ -640,6 +662,17 @@ __xfs_inode_set_reclaim_tag( | |||
640 | radix_tree_tag_set(&pag->pag_ici_root, | 662 | radix_tree_tag_set(&pag->pag_ici_root, |
641 | XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), | 663 | XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), |
642 | XFS_ICI_RECLAIM_TAG); | 664 | XFS_ICI_RECLAIM_TAG); |
665 | |||
666 | if (!pag->pag_ici_reclaimable) { | ||
667 | /* propagate the reclaim tag up into the perag radix tree */ | ||
668 | spin_lock(&ip->i_mount->m_perag_lock); | ||
669 | radix_tree_tag_set(&ip->i_mount->m_perag_tree, | ||
670 | XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), | ||
671 | XFS_ICI_RECLAIM_TAG); | ||
672 | spin_unlock(&ip->i_mount->m_perag_lock); | ||
673 | trace_xfs_perag_set_reclaim(ip->i_mount, pag->pag_agno, | ||
674 | -1, _RET_IP_); | ||
675 | } | ||
643 | pag->pag_ici_reclaimable++; | 676 | pag->pag_ici_reclaimable++; |
644 | } | 677 | } |
645 | 678 | ||
@@ -674,6 +707,16 @@ __xfs_inode_clear_reclaim_tag( | |||
674 | radix_tree_tag_clear(&pag->pag_ici_root, | 707 | radix_tree_tag_clear(&pag->pag_ici_root, |
675 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); | 708 | XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); |
676 | pag->pag_ici_reclaimable--; | 709 | pag->pag_ici_reclaimable--; |
710 | if (!pag->pag_ici_reclaimable) { | ||
711 | /* clear the reclaim tag from the perag radix tree */ | ||
712 | spin_lock(&ip->i_mount->m_perag_lock); | ||
713 | radix_tree_tag_clear(&ip->i_mount->m_perag_tree, | ||
714 | XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), | ||
715 | XFS_ICI_RECLAIM_TAG); | ||
716 | spin_unlock(&ip->i_mount->m_perag_lock); | ||
717 | trace_xfs_perag_clear_reclaim(ip->i_mount, pag->pag_agno, | ||
718 | -1, _RET_IP_); | ||
719 | } | ||
677 | } | 720 | } |
678 | 721 | ||
679 | /* | 722 | /* |
@@ -812,7 +855,36 @@ out: | |||
812 | reclaim: | 855 | reclaim: |
813 | xfs_ifunlock(ip); | 856 | xfs_ifunlock(ip); |
814 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 857 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
815 | xfs_ireclaim(ip); | 858 | |
859 | XFS_STATS_INC(xs_ig_reclaims); | ||
860 | /* | ||
861 | * Remove the inode from the per-AG radix tree. | ||
862 | * | ||
863 | * Because radix_tree_delete won't complain even if the item was never | ||
864 | * added to the tree assert that it's been there before to catch | ||
865 | * problems with the inode life time early on. | ||
866 | */ | ||
867 | write_lock(&pag->pag_ici_lock); | ||
868 | if (!radix_tree_delete(&pag->pag_ici_root, | ||
869 | XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino))) | ||
870 | ASSERT(0); | ||
871 | write_unlock(&pag->pag_ici_lock); | ||
872 | |||
873 | /* | ||
874 | * Here we do an (almost) spurious inode lock in order to coordinate | ||
875 | * with inode cache radix tree lookups. This is because the lookup | ||
876 | * can reference the inodes in the cache without taking references. | ||
877 | * | ||
878 | * We make that OK here by ensuring that we wait until the inode is | ||
879 | * unlocked after the lookup before we go ahead and free it. We get | ||
880 | * both the ilock and the iolock because the code may need to drop the | ||
881 | * ilock one but will still hold the iolock. | ||
882 | */ | ||
883 | xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
884 | xfs_qm_dqdetach(ip); | ||
885 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
886 | |||
887 | xfs_inode_free(ip); | ||
816 | return error; | 888 | return error; |
817 | 889 | ||
818 | } | 890 | } |
@@ -828,83 +900,52 @@ xfs_reclaim_inodes( | |||
828 | 900 | ||
829 | /* | 901 | /* |
830 | * Shrinker infrastructure. | 902 | * Shrinker infrastructure. |
831 | * | ||
832 | * This is all far more complex than it needs to be. It adds a global list of | ||
833 | * mounts because the shrinkers can only call a global context. We need to make | ||
834 | * the shrinkers pass a context to avoid the need for global state. | ||
835 | */ | 903 | */ |
836 | static LIST_HEAD(xfs_mount_list); | ||
837 | static struct rw_semaphore xfs_mount_list_lock; | ||
838 | |||
839 | static int | 904 | static int |
840 | xfs_reclaim_inode_shrink( | 905 | xfs_reclaim_inode_shrink( |
906 | struct shrinker *shrink, | ||
841 | int nr_to_scan, | 907 | int nr_to_scan, |
842 | gfp_t gfp_mask) | 908 | gfp_t gfp_mask) |
843 | { | 909 | { |
844 | struct xfs_mount *mp; | 910 | struct xfs_mount *mp; |
845 | struct xfs_perag *pag; | 911 | struct xfs_perag *pag; |
846 | xfs_agnumber_t ag; | 912 | xfs_agnumber_t ag; |
847 | int reclaimable = 0; | 913 | int reclaimable; |
848 | 914 | ||
915 | mp = container_of(shrink, struct xfs_mount, m_inode_shrink); | ||
849 | if (nr_to_scan) { | 916 | if (nr_to_scan) { |
850 | if (!(gfp_mask & __GFP_FS)) | 917 | if (!(gfp_mask & __GFP_FS)) |
851 | return -1; | 918 | return -1; |
852 | 919 | ||
853 | down_read(&xfs_mount_list_lock); | 920 | xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0, |
854 | list_for_each_entry(mp, &xfs_mount_list, m_mplist) { | ||
855 | xfs_inode_ag_iterator(mp, xfs_reclaim_inode, 0, | ||
856 | XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan); | 921 | XFS_ICI_RECLAIM_TAG, 1, &nr_to_scan); |
857 | if (nr_to_scan <= 0) | 922 | /* if we don't exhaust the scan, don't bother coming back */ |
858 | break; | 923 | if (nr_to_scan > 0) |
859 | } | 924 | return -1; |
860 | up_read(&xfs_mount_list_lock); | 925 | } |
861 | } | ||
862 | 926 | ||
863 | down_read(&xfs_mount_list_lock); | 927 | reclaimable = 0; |
864 | list_for_each_entry(mp, &xfs_mount_list, m_mplist) { | 928 | ag = 0; |
865 | for (ag = 0; ag < mp->m_sb.sb_agcount; ag++) { | 929 | while ((pag = xfs_inode_ag_iter_next_pag(mp, &ag, |
866 | pag = xfs_perag_get(mp, ag); | 930 | XFS_ICI_RECLAIM_TAG))) { |
867 | reclaimable += pag->pag_ici_reclaimable; | 931 | reclaimable += pag->pag_ici_reclaimable; |
868 | xfs_perag_put(pag); | 932 | xfs_perag_put(pag); |
869 | } | ||
870 | } | 933 | } |
871 | up_read(&xfs_mount_list_lock); | ||
872 | return reclaimable; | 934 | return reclaimable; |
873 | } | 935 | } |
874 | 936 | ||
875 | static struct shrinker xfs_inode_shrinker = { | ||
876 | .shrink = xfs_reclaim_inode_shrink, | ||
877 | .seeks = DEFAULT_SEEKS, | ||
878 | }; | ||
879 | |||
880 | void __init | ||
881 | xfs_inode_shrinker_init(void) | ||
882 | { | ||
883 | init_rwsem(&xfs_mount_list_lock); | ||
884 | register_shrinker(&xfs_inode_shrinker); | ||
885 | } | ||
886 | |||
887 | void | ||
888 | xfs_inode_shrinker_destroy(void) | ||
889 | { | ||
890 | ASSERT(list_empty(&xfs_mount_list)); | ||
891 | unregister_shrinker(&xfs_inode_shrinker); | ||
892 | } | ||
893 | |||
894 | void | 937 | void |
895 | xfs_inode_shrinker_register( | 938 | xfs_inode_shrinker_register( |
896 | struct xfs_mount *mp) | 939 | struct xfs_mount *mp) |
897 | { | 940 | { |
898 | down_write(&xfs_mount_list_lock); | 941 | mp->m_inode_shrink.shrink = xfs_reclaim_inode_shrink; |
899 | list_add_tail(&mp->m_mplist, &xfs_mount_list); | 942 | mp->m_inode_shrink.seeks = DEFAULT_SEEKS; |
900 | up_write(&xfs_mount_list_lock); | 943 | register_shrinker(&mp->m_inode_shrink); |
901 | } | 944 | } |
902 | 945 | ||
903 | void | 946 | void |
904 | xfs_inode_shrinker_unregister( | 947 | xfs_inode_shrinker_unregister( |
905 | struct xfs_mount *mp) | 948 | struct xfs_mount *mp) |
906 | { | 949 | { |
907 | down_write(&xfs_mount_list_lock); | 950 | unregister_shrinker(&mp->m_inode_shrink); |
908 | list_del(&mp->m_mplist); | ||
909 | up_write(&xfs_mount_list_lock); | ||
910 | } | 951 | } |
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index cdcbaaca9880..fe78726196f8 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h | |||
@@ -35,9 +35,6 @@ typedef struct xfs_sync_work { | |||
35 | int xfs_syncd_init(struct xfs_mount *mp); | 35 | int xfs_syncd_init(struct xfs_mount *mp); |
36 | void xfs_syncd_stop(struct xfs_mount *mp); | 36 | void xfs_syncd_stop(struct xfs_mount *mp); |
37 | 37 | ||
38 | int xfs_sync_attr(struct xfs_mount *mp, int flags); | ||
39 | int xfs_sync_data(struct xfs_mount *mp, int flags); | ||
40 | |||
41 | int xfs_quiesce_data(struct xfs_mount *mp); | 38 | int xfs_quiesce_data(struct xfs_mount *mp); |
42 | void xfs_quiesce_attr(struct xfs_mount *mp); | 39 | void xfs_quiesce_attr(struct xfs_mount *mp); |
43 | 40 | ||
@@ -55,8 +52,6 @@ int xfs_inode_ag_iterator(struct xfs_mount *mp, | |||
55 | int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), | 52 | int (*execute)(struct xfs_inode *ip, struct xfs_perag *pag, int flags), |
56 | int flags, int tag, int write_lock, int *nr_to_scan); | 53 | int flags, int tag, int write_lock, int *nr_to_scan); |
57 | 54 | ||
58 | void xfs_inode_shrinker_init(void); | ||
59 | void xfs_inode_shrinker_destroy(void); | ||
60 | void xfs_inode_shrinker_register(struct xfs_mount *mp); | 55 | void xfs_inode_shrinker_register(struct xfs_mount *mp); |
61 | void xfs_inode_shrinker_unregister(struct xfs_mount *mp); | 56 | void xfs_inode_shrinker_unregister(struct xfs_mount *mp); |
62 | 57 | ||
diff --git a/fs/xfs/linux-2.6/xfs_trace.c b/fs/xfs/linux-2.6/xfs_trace.c index d12be8470cba..88d25d4aa56e 100644 --- a/fs/xfs/linux-2.6/xfs_trace.c +++ b/fs/xfs/linux-2.6/xfs_trace.c | |||
@@ -24,17 +24,13 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_da_btree.h" | 27 | #include "xfs_da_btree.h" |
29 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
30 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
31 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
32 | #include "xfs_dir2_sf.h" | ||
33 | #include "xfs_attr_sf.h" | ||
34 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
35 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
36 | #include "xfs_btree.h" | 33 | #include "xfs_btree.h" |
37 | #include "xfs_dmapi.h" | ||
38 | #include "xfs_mount.h" | 34 | #include "xfs_mount.h" |
39 | #include "xfs_ialloc.h" | 35 | #include "xfs_ialloc.h" |
40 | #include "xfs_itable.h" | 36 | #include "xfs_itable.h" |
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h index 73d5aa117384..c657cdca2cd2 100644 --- a/fs/xfs/linux-2.6/xfs_trace.h +++ b/fs/xfs/linux-2.6/xfs_trace.h | |||
@@ -124,7 +124,10 @@ DEFINE_EVENT(xfs_perag_class, name, \ | |||
124 | unsigned long caller_ip), \ | 124 | unsigned long caller_ip), \ |
125 | TP_ARGS(mp, agno, refcount, caller_ip)) | 125 | TP_ARGS(mp, agno, refcount, caller_ip)) |
126 | DEFINE_PERAG_REF_EVENT(xfs_perag_get); | 126 | DEFINE_PERAG_REF_EVENT(xfs_perag_get); |
127 | DEFINE_PERAG_REF_EVENT(xfs_perag_get_reclaim); | ||
127 | DEFINE_PERAG_REF_EVENT(xfs_perag_put); | 128 | DEFINE_PERAG_REF_EVENT(xfs_perag_put); |
129 | DEFINE_PERAG_REF_EVENT(xfs_perag_set_reclaim); | ||
130 | DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim); | ||
128 | 131 | ||
129 | TRACE_EVENT(xfs_attr_list_node_descend, | 132 | TRACE_EVENT(xfs_attr_list_node_descend, |
130 | TP_PROTO(struct xfs_attr_list_context *ctx, | 133 | TP_PROTO(struct xfs_attr_list_context *ctx, |
@@ -314,8 +317,6 @@ DEFINE_BUF_EVENT(xfs_buf_init); | |||
314 | DEFINE_BUF_EVENT(xfs_buf_free); | 317 | DEFINE_BUF_EVENT(xfs_buf_free); |
315 | DEFINE_BUF_EVENT(xfs_buf_hold); | 318 | DEFINE_BUF_EVENT(xfs_buf_hold); |
316 | DEFINE_BUF_EVENT(xfs_buf_rele); | 319 | DEFINE_BUF_EVENT(xfs_buf_rele); |
317 | DEFINE_BUF_EVENT(xfs_buf_pin); | ||
318 | DEFINE_BUF_EVENT(xfs_buf_unpin); | ||
319 | DEFINE_BUF_EVENT(xfs_buf_iodone); | 320 | DEFINE_BUF_EVENT(xfs_buf_iodone); |
320 | DEFINE_BUF_EVENT(xfs_buf_iorequest); | 321 | DEFINE_BUF_EVENT(xfs_buf_iorequest); |
321 | DEFINE_BUF_EVENT(xfs_buf_bawrite); | 322 | DEFINE_BUF_EVENT(xfs_buf_bawrite); |
@@ -538,7 +539,7 @@ DEFINE_LOCK_EVENT(xfs_ilock_nowait); | |||
538 | DEFINE_LOCK_EVENT(xfs_ilock_demote); | 539 | DEFINE_LOCK_EVENT(xfs_ilock_demote); |
539 | DEFINE_LOCK_EVENT(xfs_iunlock); | 540 | DEFINE_LOCK_EVENT(xfs_iunlock); |
540 | 541 | ||
541 | DECLARE_EVENT_CLASS(xfs_iget_class, | 542 | DECLARE_EVENT_CLASS(xfs_inode_class, |
542 | TP_PROTO(struct xfs_inode *ip), | 543 | TP_PROTO(struct xfs_inode *ip), |
543 | TP_ARGS(ip), | 544 | TP_ARGS(ip), |
544 | TP_STRUCT__entry( | 545 | TP_STRUCT__entry( |
@@ -554,16 +555,38 @@ DECLARE_EVENT_CLASS(xfs_iget_class, | |||
554 | __entry->ino) | 555 | __entry->ino) |
555 | ) | 556 | ) |
556 | 557 | ||
557 | #define DEFINE_IGET_EVENT(name) \ | 558 | #define DEFINE_INODE_EVENT(name) \ |
558 | DEFINE_EVENT(xfs_iget_class, name, \ | 559 | DEFINE_EVENT(xfs_inode_class, name, \ |
559 | TP_PROTO(struct xfs_inode *ip), \ | 560 | TP_PROTO(struct xfs_inode *ip), \ |
560 | TP_ARGS(ip)) | 561 | TP_ARGS(ip)) |
561 | DEFINE_IGET_EVENT(xfs_iget_skip); | 562 | DEFINE_INODE_EVENT(xfs_iget_skip); |
562 | DEFINE_IGET_EVENT(xfs_iget_reclaim); | 563 | DEFINE_INODE_EVENT(xfs_iget_reclaim); |
563 | DEFINE_IGET_EVENT(xfs_iget_found); | 564 | DEFINE_INODE_EVENT(xfs_iget_reclaim_fail); |
564 | DEFINE_IGET_EVENT(xfs_iget_alloc); | 565 | DEFINE_INODE_EVENT(xfs_iget_hit); |
565 | 566 | DEFINE_INODE_EVENT(xfs_iget_miss); | |
566 | DECLARE_EVENT_CLASS(xfs_inode_class, | 567 | |
568 | DEFINE_INODE_EVENT(xfs_getattr); | ||
569 | DEFINE_INODE_EVENT(xfs_setattr); | ||
570 | DEFINE_INODE_EVENT(xfs_readlink); | ||
571 | DEFINE_INODE_EVENT(xfs_alloc_file_space); | ||
572 | DEFINE_INODE_EVENT(xfs_free_file_space); | ||
573 | DEFINE_INODE_EVENT(xfs_readdir); | ||
574 | #ifdef CONFIG_XFS_POSIX_ACL | ||
575 | DEFINE_INODE_EVENT(xfs_check_acl); | ||
576 | #endif | ||
577 | DEFINE_INODE_EVENT(xfs_vm_bmap); | ||
578 | DEFINE_INODE_EVENT(xfs_file_ioctl); | ||
579 | DEFINE_INODE_EVENT(xfs_file_compat_ioctl); | ||
580 | DEFINE_INODE_EVENT(xfs_ioctl_setattr); | ||
581 | DEFINE_INODE_EVENT(xfs_file_fsync); | ||
582 | DEFINE_INODE_EVENT(xfs_destroy_inode); | ||
583 | DEFINE_INODE_EVENT(xfs_write_inode); | ||
584 | DEFINE_INODE_EVENT(xfs_clear_inode); | ||
585 | |||
586 | DEFINE_INODE_EVENT(xfs_dquot_dqalloc); | ||
587 | DEFINE_INODE_EVENT(xfs_dquot_dqdetach); | ||
588 | |||
589 | DECLARE_EVENT_CLASS(xfs_iref_class, | ||
567 | TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), | 590 | TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), |
568 | TP_ARGS(ip, caller_ip), | 591 | TP_ARGS(ip, caller_ip), |
569 | TP_STRUCT__entry( | 592 | TP_STRUCT__entry( |
@@ -588,20 +611,71 @@ DECLARE_EVENT_CLASS(xfs_inode_class, | |||
588 | (char *)__entry->caller_ip) | 611 | (char *)__entry->caller_ip) |
589 | ) | 612 | ) |
590 | 613 | ||
591 | #define DEFINE_INODE_EVENT(name) \ | 614 | #define DEFINE_IREF_EVENT(name) \ |
592 | DEFINE_EVENT(xfs_inode_class, name, \ | 615 | DEFINE_EVENT(xfs_iref_class, name, \ |
593 | TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), \ | 616 | TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), \ |
594 | TP_ARGS(ip, caller_ip)) | 617 | TP_ARGS(ip, caller_ip)) |
595 | DEFINE_INODE_EVENT(xfs_ihold); | 618 | DEFINE_IREF_EVENT(xfs_ihold); |
596 | DEFINE_INODE_EVENT(xfs_irele); | 619 | DEFINE_IREF_EVENT(xfs_irele); |
597 | DEFINE_INODE_EVENT(xfs_inode_pin); | 620 | DEFINE_IREF_EVENT(xfs_inode_pin); |
598 | DEFINE_INODE_EVENT(xfs_inode_unpin); | 621 | DEFINE_IREF_EVENT(xfs_inode_unpin); |
599 | DEFINE_INODE_EVENT(xfs_inode_unpin_nowait); | 622 | DEFINE_IREF_EVENT(xfs_inode_unpin_nowait); |
623 | |||
624 | DECLARE_EVENT_CLASS(xfs_namespace_class, | ||
625 | TP_PROTO(struct xfs_inode *dp, struct xfs_name *name), | ||
626 | TP_ARGS(dp, name), | ||
627 | TP_STRUCT__entry( | ||
628 | __field(dev_t, dev) | ||
629 | __field(xfs_ino_t, dp_ino) | ||
630 | __dynamic_array(char, name, name->len) | ||
631 | ), | ||
632 | TP_fast_assign( | ||
633 | __entry->dev = VFS_I(dp)->i_sb->s_dev; | ||
634 | __entry->dp_ino = dp->i_ino; | ||
635 | memcpy(__get_str(name), name->name, name->len); | ||
636 | ), | ||
637 | TP_printk("dev %d:%d dp ino 0x%llx name %s", | ||
638 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
639 | __entry->dp_ino, | ||
640 | __get_str(name)) | ||
641 | ) | ||
600 | 642 | ||
601 | /* the old xfs_itrace_entry tracer - to be replaced by s.th. in the VFS */ | 643 | #define DEFINE_NAMESPACE_EVENT(name) \ |
602 | DEFINE_INODE_EVENT(xfs_inode); | 644 | DEFINE_EVENT(xfs_namespace_class, name, \ |
603 | #define xfs_itrace_entry(ip) \ | 645 | TP_PROTO(struct xfs_inode *dp, struct xfs_name *name), \ |
604 | trace_xfs_inode(ip, _THIS_IP_) | 646 | TP_ARGS(dp, name)) |
647 | DEFINE_NAMESPACE_EVENT(xfs_remove); | ||
648 | DEFINE_NAMESPACE_EVENT(xfs_link); | ||
649 | DEFINE_NAMESPACE_EVENT(xfs_lookup); | ||
650 | DEFINE_NAMESPACE_EVENT(xfs_create); | ||
651 | DEFINE_NAMESPACE_EVENT(xfs_symlink); | ||
652 | |||
653 | TRACE_EVENT(xfs_rename, | ||
654 | TP_PROTO(struct xfs_inode *src_dp, struct xfs_inode *target_dp, | ||
655 | struct xfs_name *src_name, struct xfs_name *target_name), | ||
656 | TP_ARGS(src_dp, target_dp, src_name, target_name), | ||
657 | TP_STRUCT__entry( | ||
658 | __field(dev_t, dev) | ||
659 | __field(xfs_ino_t, src_dp_ino) | ||
660 | __field(xfs_ino_t, target_dp_ino) | ||
661 | __dynamic_array(char, src_name, src_name->len) | ||
662 | __dynamic_array(char, target_name, target_name->len) | ||
663 | ), | ||
664 | TP_fast_assign( | ||
665 | __entry->dev = VFS_I(src_dp)->i_sb->s_dev; | ||
666 | __entry->src_dp_ino = src_dp->i_ino; | ||
667 | __entry->target_dp_ino = target_dp->i_ino; | ||
668 | memcpy(__get_str(src_name), src_name->name, src_name->len); | ||
669 | memcpy(__get_str(target_name), target_name->name, target_name->len); | ||
670 | ), | ||
671 | TP_printk("dev %d:%d src dp ino 0x%llx target dp ino 0x%llx" | ||
672 | " src name %s target name %s", | ||
673 | MAJOR(__entry->dev), MINOR(__entry->dev), | ||
674 | __entry->src_dp_ino, | ||
675 | __entry->target_dp_ino, | ||
676 | __get_str(src_name), | ||
677 | __get_str(target_name)) | ||
678 | ) | ||
605 | 679 | ||
606 | DECLARE_EVENT_CLASS(xfs_dquot_class, | 680 | DECLARE_EVENT_CLASS(xfs_dquot_class, |
607 | TP_PROTO(struct xfs_dquot *dqp), | 681 | TP_PROTO(struct xfs_dquot *dqp), |
@@ -681,9 +755,6 @@ DEFINE_DQUOT_EVENT(xfs_dqrele); | |||
681 | DEFINE_DQUOT_EVENT(xfs_dqflush); | 755 | DEFINE_DQUOT_EVENT(xfs_dqflush); |
682 | DEFINE_DQUOT_EVENT(xfs_dqflush_force); | 756 | DEFINE_DQUOT_EVENT(xfs_dqflush_force); |
683 | DEFINE_DQUOT_EVENT(xfs_dqflush_done); | 757 | DEFINE_DQUOT_EVENT(xfs_dqflush_done); |
684 | /* not really iget events, but we re-use the format */ | ||
685 | DEFINE_IGET_EVENT(xfs_dquot_dqalloc); | ||
686 | DEFINE_IGET_EVENT(xfs_dquot_dqdetach); | ||
687 | 758 | ||
688 | DECLARE_EVENT_CLASS(xfs_loggrant_class, | 759 | DECLARE_EVENT_CLASS(xfs_loggrant_class, |
689 | TP_PROTO(struct log *log, struct xlog_ticket *tic), | 760 | TP_PROTO(struct log *log, struct xlog_ticket *tic), |
@@ -831,33 +902,29 @@ DECLARE_EVENT_CLASS(xfs_page_class, | |||
831 | __field(loff_t, size) | 902 | __field(loff_t, size) |
832 | __field(unsigned long, offset) | 903 | __field(unsigned long, offset) |
833 | __field(int, delalloc) | 904 | __field(int, delalloc) |
834 | __field(int, unmapped) | ||
835 | __field(int, unwritten) | 905 | __field(int, unwritten) |
836 | ), | 906 | ), |
837 | TP_fast_assign( | 907 | TP_fast_assign( |
838 | int delalloc = -1, unmapped = -1, unwritten = -1; | 908 | int delalloc = -1, unwritten = -1; |
839 | 909 | ||
840 | if (page_has_buffers(page)) | 910 | if (page_has_buffers(page)) |
841 | xfs_count_page_state(page, &delalloc, | 911 | xfs_count_page_state(page, &delalloc, &unwritten); |
842 | &unmapped, &unwritten); | ||
843 | __entry->dev = inode->i_sb->s_dev; | 912 | __entry->dev = inode->i_sb->s_dev; |
844 | __entry->ino = XFS_I(inode)->i_ino; | 913 | __entry->ino = XFS_I(inode)->i_ino; |
845 | __entry->pgoff = page_offset(page); | 914 | __entry->pgoff = page_offset(page); |
846 | __entry->size = i_size_read(inode); | 915 | __entry->size = i_size_read(inode); |
847 | __entry->offset = off; | 916 | __entry->offset = off; |
848 | __entry->delalloc = delalloc; | 917 | __entry->delalloc = delalloc; |
849 | __entry->unmapped = unmapped; | ||
850 | __entry->unwritten = unwritten; | 918 | __entry->unwritten = unwritten; |
851 | ), | 919 | ), |
852 | TP_printk("dev %d:%d ino 0x%llx pgoff 0x%lx size 0x%llx offset %lx " | 920 | TP_printk("dev %d:%d ino 0x%llx pgoff 0x%lx size 0x%llx offset %lx " |
853 | "delalloc %d unmapped %d unwritten %d", | 921 | "delalloc %d unwritten %d", |
854 | MAJOR(__entry->dev), MINOR(__entry->dev), | 922 | MAJOR(__entry->dev), MINOR(__entry->dev), |
855 | __entry->ino, | 923 | __entry->ino, |
856 | __entry->pgoff, | 924 | __entry->pgoff, |
857 | __entry->size, | 925 | __entry->size, |
858 | __entry->offset, | 926 | __entry->offset, |
859 | __entry->delalloc, | 927 | __entry->delalloc, |
860 | __entry->unmapped, | ||
861 | __entry->unwritten) | 928 | __entry->unwritten) |
862 | ) | 929 | ) |
863 | 930 | ||
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 585e7633dfc7..e1a2f6800e01 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c | |||
@@ -23,25 +23,15 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | ||
27 | #include "xfs_alloc.h" | 26 | #include "xfs_alloc.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_quota.h" | 27 | #include "xfs_quota.h" |
30 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | ||
33 | #include "xfs_ialloc_btree.h" | ||
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | ||
37 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
38 | #include "xfs_btree.h" | ||
39 | #include "xfs_ialloc.h" | ||
40 | #include "xfs_bmap.h" | 31 | #include "xfs_bmap.h" |
41 | #include "xfs_rtalloc.h" | 32 | #include "xfs_rtalloc.h" |
42 | #include "xfs_error.h" | 33 | #include "xfs_error.h" |
43 | #include "xfs_itable.h" | 34 | #include "xfs_itable.h" |
44 | #include "xfs_rw.h" | ||
45 | #include "xfs_attr.h" | 35 | #include "xfs_attr.h" |
46 | #include "xfs_buf_item.h" | 36 | #include "xfs_buf_item.h" |
47 | #include "xfs_trans_space.h" | 37 | #include "xfs_trans_space.h" |
@@ -64,8 +54,6 @@ | |||
64 | flush lock - ditto. | 54 | flush lock - ditto. |
65 | */ | 55 | */ |
66 | 56 | ||
67 | STATIC void xfs_qm_dqflush_done(xfs_buf_t *, xfs_dq_logitem_t *); | ||
68 | |||
69 | #ifdef DEBUG | 57 | #ifdef DEBUG |
70 | xfs_buftarg_t *xfs_dqerror_target; | 58 | xfs_buftarg_t *xfs_dqerror_target; |
71 | int xfs_do_dqerror; | 59 | int xfs_do_dqerror; |
@@ -390,21 +378,14 @@ xfs_qm_dqalloc( | |||
390 | return (ESRCH); | 378 | return (ESRCH); |
391 | } | 379 | } |
392 | 380 | ||
393 | /* | 381 | xfs_trans_ijoin_ref(tp, quotip, XFS_ILOCK_EXCL); |
394 | * xfs_trans_commit normally decrements the vnode ref count | ||
395 | * when it unlocks the inode. Since we want to keep the quota | ||
396 | * inode around, we bump the vnode ref count now. | ||
397 | */ | ||
398 | IHOLD(quotip); | ||
399 | |||
400 | xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL); | ||
401 | nmaps = 1; | 382 | nmaps = 1; |
402 | if ((error = xfs_bmapi(tp, quotip, | 383 | if ((error = xfs_bmapi(tp, quotip, |
403 | offset_fsb, XFS_DQUOT_CLUSTER_SIZE_FSB, | 384 | offset_fsb, XFS_DQUOT_CLUSTER_SIZE_FSB, |
404 | XFS_BMAPI_METADATA | XFS_BMAPI_WRITE, | 385 | XFS_BMAPI_METADATA | XFS_BMAPI_WRITE, |
405 | &firstblock, | 386 | &firstblock, |
406 | XFS_QM_DQALLOC_SPACE_RES(mp), | 387 | XFS_QM_DQALLOC_SPACE_RES(mp), |
407 | &map, &nmaps, &flist, NULL))) { | 388 | &map, &nmaps, &flist))) { |
408 | goto error0; | 389 | goto error0; |
409 | } | 390 | } |
410 | ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB); | 391 | ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB); |
@@ -520,7 +501,7 @@ xfs_qm_dqtobp( | |||
520 | error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset, | 501 | error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset, |
521 | XFS_DQUOT_CLUSTER_SIZE_FSB, | 502 | XFS_DQUOT_CLUSTER_SIZE_FSB, |
522 | XFS_BMAPI_METADATA, | 503 | XFS_BMAPI_METADATA, |
523 | NULL, 0, &map, &nmaps, NULL, NULL); | 504 | NULL, 0, &map, &nmaps, NULL); |
524 | 505 | ||
525 | xfs_iunlock(quotip, XFS_ILOCK_SHARED); | 506 | xfs_iunlock(quotip, XFS_ILOCK_SHARED); |
526 | if (error) | 507 | if (error) |
@@ -1141,6 +1122,46 @@ xfs_qm_dqrele( | |||
1141 | xfs_qm_dqput(dqp); | 1122 | xfs_qm_dqput(dqp); |
1142 | } | 1123 | } |
1143 | 1124 | ||
1125 | /* | ||
1126 | * This is the dquot flushing I/O completion routine. It is called | ||
1127 | * from interrupt level when the buffer containing the dquot is | ||
1128 | * flushed to disk. It is responsible for removing the dquot logitem | ||
1129 | * from the AIL if it has not been re-logged, and unlocking the dquot's | ||
1130 | * flush lock. This behavior is very similar to that of inodes.. | ||
1131 | */ | ||
1132 | STATIC void | ||
1133 | xfs_qm_dqflush_done( | ||
1134 | struct xfs_buf *bp, | ||
1135 | struct xfs_log_item *lip) | ||
1136 | { | ||
1137 | xfs_dq_logitem_t *qip = (struct xfs_dq_logitem *)lip; | ||
1138 | xfs_dquot_t *dqp = qip->qli_dquot; | ||
1139 | struct xfs_ail *ailp = lip->li_ailp; | ||
1140 | |||
1141 | /* | ||
1142 | * We only want to pull the item from the AIL if its | ||
1143 | * location in the log has not changed since we started the flush. | ||
1144 | * Thus, we only bother if the dquot's lsn has | ||
1145 | * not changed. First we check the lsn outside the lock | ||
1146 | * since it's cheaper, and then we recheck while | ||
1147 | * holding the lock before removing the dquot from the AIL. | ||
1148 | */ | ||
1149 | if ((lip->li_flags & XFS_LI_IN_AIL) && | ||
1150 | lip->li_lsn == qip->qli_flush_lsn) { | ||
1151 | |||
1152 | /* xfs_trans_ail_delete() drops the AIL lock. */ | ||
1153 | spin_lock(&ailp->xa_lock); | ||
1154 | if (lip->li_lsn == qip->qli_flush_lsn) | ||
1155 | xfs_trans_ail_delete(ailp, lip); | ||
1156 | else | ||
1157 | spin_unlock(&ailp->xa_lock); | ||
1158 | } | ||
1159 | |||
1160 | /* | ||
1161 | * Release the dq's flush lock since we're done with it. | ||
1162 | */ | ||
1163 | xfs_dqfunlock(dqp); | ||
1164 | } | ||
1144 | 1165 | ||
1145 | /* | 1166 | /* |
1146 | * Write a modified dquot to disk. | 1167 | * Write a modified dquot to disk. |
@@ -1222,8 +1243,9 @@ xfs_qm_dqflush( | |||
1222 | * Attach an iodone routine so that we can remove this dquot from the | 1243 | * Attach an iodone routine so that we can remove this dquot from the |
1223 | * AIL and release the flush lock once the dquot is synced to disk. | 1244 | * AIL and release the flush lock once the dquot is synced to disk. |
1224 | */ | 1245 | */ |
1225 | xfs_buf_attach_iodone(bp, (void(*)(xfs_buf_t *, xfs_log_item_t *)) | 1246 | xfs_buf_attach_iodone(bp, xfs_qm_dqflush_done, |
1226 | xfs_qm_dqflush_done, &(dqp->q_logitem.qli_item)); | 1247 | &dqp->q_logitem.qli_item); |
1248 | |||
1227 | /* | 1249 | /* |
1228 | * If the buffer is pinned then push on the log so we won't | 1250 | * If the buffer is pinned then push on the log so we won't |
1229 | * get stuck waiting in the write for too long. | 1251 | * get stuck waiting in the write for too long. |
@@ -1247,50 +1269,6 @@ xfs_qm_dqflush( | |||
1247 | 1269 | ||
1248 | } | 1270 | } |
1249 | 1271 | ||
1250 | /* | ||
1251 | * This is the dquot flushing I/O completion routine. It is called | ||
1252 | * from interrupt level when the buffer containing the dquot is | ||
1253 | * flushed to disk. It is responsible for removing the dquot logitem | ||
1254 | * from the AIL if it has not been re-logged, and unlocking the dquot's | ||
1255 | * flush lock. This behavior is very similar to that of inodes.. | ||
1256 | */ | ||
1257 | /*ARGSUSED*/ | ||
1258 | STATIC void | ||
1259 | xfs_qm_dqflush_done( | ||
1260 | xfs_buf_t *bp, | ||
1261 | xfs_dq_logitem_t *qip) | ||
1262 | { | ||
1263 | xfs_dquot_t *dqp; | ||
1264 | struct xfs_ail *ailp; | ||
1265 | |||
1266 | dqp = qip->qli_dquot; | ||
1267 | ailp = qip->qli_item.li_ailp; | ||
1268 | |||
1269 | /* | ||
1270 | * We only want to pull the item from the AIL if its | ||
1271 | * location in the log has not changed since we started the flush. | ||
1272 | * Thus, we only bother if the dquot's lsn has | ||
1273 | * not changed. First we check the lsn outside the lock | ||
1274 | * since it's cheaper, and then we recheck while | ||
1275 | * holding the lock before removing the dquot from the AIL. | ||
1276 | */ | ||
1277 | if ((qip->qli_item.li_flags & XFS_LI_IN_AIL) && | ||
1278 | qip->qli_item.li_lsn == qip->qli_flush_lsn) { | ||
1279 | |||
1280 | /* xfs_trans_ail_delete() drops the AIL lock. */ | ||
1281 | spin_lock(&ailp->xa_lock); | ||
1282 | if (qip->qli_item.li_lsn == qip->qli_flush_lsn) | ||
1283 | xfs_trans_ail_delete(ailp, (xfs_log_item_t*)qip); | ||
1284 | else | ||
1285 | spin_unlock(&ailp->xa_lock); | ||
1286 | } | ||
1287 | |||
1288 | /* | ||
1289 | * Release the dq's flush lock since we're done with it. | ||
1290 | */ | ||
1291 | xfs_dqfunlock(dqp); | ||
1292 | } | ||
1293 | |||
1294 | int | 1272 | int |
1295 | xfs_qm_dqlock_nowait( | 1273 | xfs_qm_dqlock_nowait( |
1296 | xfs_dquot_t *dqp) | 1274 | xfs_dquot_t *dqp) |
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 8d89a24ae324..2a1f3dc10a02 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c | |||
@@ -23,42 +23,36 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | ||
27 | #include "xfs_alloc.h" | 26 | #include "xfs_alloc.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_quota.h" | 27 | #include "xfs_quota.h" |
30 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | ||
33 | #include "xfs_ialloc_btree.h" | ||
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | ||
37 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
38 | #include "xfs_bmap.h" | 31 | #include "xfs_bmap.h" |
39 | #include "xfs_btree.h" | ||
40 | #include "xfs_ialloc.h" | ||
41 | #include "xfs_rtalloc.h" | 32 | #include "xfs_rtalloc.h" |
42 | #include "xfs_error.h" | 33 | #include "xfs_error.h" |
43 | #include "xfs_itable.h" | 34 | #include "xfs_itable.h" |
44 | #include "xfs_rw.h" | ||
45 | #include "xfs_attr.h" | 35 | #include "xfs_attr.h" |
46 | #include "xfs_buf_item.h" | 36 | #include "xfs_buf_item.h" |
47 | #include "xfs_trans_priv.h" | 37 | #include "xfs_trans_priv.h" |
48 | #include "xfs_qm.h" | 38 | #include "xfs_qm.h" |
49 | 39 | ||
40 | static inline struct xfs_dq_logitem *DQUOT_ITEM(struct xfs_log_item *lip) | ||
41 | { | ||
42 | return container_of(lip, struct xfs_dq_logitem, qli_item); | ||
43 | } | ||
44 | |||
50 | /* | 45 | /* |
51 | * returns the number of iovecs needed to log the given dquot item. | 46 | * returns the number of iovecs needed to log the given dquot item. |
52 | */ | 47 | */ |
53 | /* ARGSUSED */ | ||
54 | STATIC uint | 48 | STATIC uint |
55 | xfs_qm_dquot_logitem_size( | 49 | xfs_qm_dquot_logitem_size( |
56 | xfs_dq_logitem_t *logitem) | 50 | struct xfs_log_item *lip) |
57 | { | 51 | { |
58 | /* | 52 | /* |
59 | * we need only two iovecs, one for the format, one for the real thing | 53 | * we need only two iovecs, one for the format, one for the real thing |
60 | */ | 54 | */ |
61 | return (2); | 55 | return 2; |
62 | } | 56 | } |
63 | 57 | ||
64 | /* | 58 | /* |
@@ -66,22 +60,21 @@ xfs_qm_dquot_logitem_size( | |||
66 | */ | 60 | */ |
67 | STATIC void | 61 | STATIC void |
68 | xfs_qm_dquot_logitem_format( | 62 | xfs_qm_dquot_logitem_format( |
69 | xfs_dq_logitem_t *logitem, | 63 | struct xfs_log_item *lip, |
70 | xfs_log_iovec_t *logvec) | 64 | struct xfs_log_iovec *logvec) |
71 | { | 65 | { |
72 | ASSERT(logitem); | 66 | struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip); |
73 | ASSERT(logitem->qli_dquot); | ||
74 | 67 | ||
75 | logvec->i_addr = (xfs_caddr_t)&logitem->qli_format; | 68 | logvec->i_addr = &qlip->qli_format; |
76 | logvec->i_len = sizeof(xfs_dq_logformat_t); | 69 | logvec->i_len = sizeof(xfs_dq_logformat_t); |
77 | logvec->i_type = XLOG_REG_TYPE_QFORMAT; | 70 | logvec->i_type = XLOG_REG_TYPE_QFORMAT; |
78 | logvec++; | 71 | logvec++; |
79 | logvec->i_addr = (xfs_caddr_t)&logitem->qli_dquot->q_core; | 72 | logvec->i_addr = &qlip->qli_dquot->q_core; |
80 | logvec->i_len = sizeof(xfs_disk_dquot_t); | 73 | logvec->i_len = sizeof(xfs_disk_dquot_t); |
81 | logvec->i_type = XLOG_REG_TYPE_DQUOT; | 74 | logvec->i_type = XLOG_REG_TYPE_DQUOT; |
82 | 75 | ||
83 | ASSERT(2 == logitem->qli_item.li_desc->lid_size); | 76 | ASSERT(2 == lip->li_desc->lid_size); |
84 | logitem->qli_format.qlf_size = 2; | 77 | qlip->qli_format.qlf_size = 2; |
85 | 78 | ||
86 | } | 79 | } |
87 | 80 | ||
@@ -90,9 +83,9 @@ xfs_qm_dquot_logitem_format( | |||
90 | */ | 83 | */ |
91 | STATIC void | 84 | STATIC void |
92 | xfs_qm_dquot_logitem_pin( | 85 | xfs_qm_dquot_logitem_pin( |
93 | xfs_dq_logitem_t *logitem) | 86 | struct xfs_log_item *lip) |
94 | { | 87 | { |
95 | xfs_dquot_t *dqp = logitem->qli_dquot; | 88 | struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; |
96 | 89 | ||
97 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 90 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); |
98 | atomic_inc(&dqp->q_pincount); | 91 | atomic_inc(&dqp->q_pincount); |
@@ -104,27 +97,18 @@ xfs_qm_dquot_logitem_pin( | |||
104 | * dquot must have been previously pinned with a call to | 97 | * dquot must have been previously pinned with a call to |
105 | * xfs_qm_dquot_logitem_pin(). | 98 | * xfs_qm_dquot_logitem_pin(). |
106 | */ | 99 | */ |
107 | /* ARGSUSED */ | ||
108 | STATIC void | 100 | STATIC void |
109 | xfs_qm_dquot_logitem_unpin( | 101 | xfs_qm_dquot_logitem_unpin( |
110 | xfs_dq_logitem_t *logitem) | 102 | struct xfs_log_item *lip, |
103 | int remove) | ||
111 | { | 104 | { |
112 | xfs_dquot_t *dqp = logitem->qli_dquot; | 105 | struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; |
113 | 106 | ||
114 | ASSERT(atomic_read(&dqp->q_pincount) > 0); | 107 | ASSERT(atomic_read(&dqp->q_pincount) > 0); |
115 | if (atomic_dec_and_test(&dqp->q_pincount)) | 108 | if (atomic_dec_and_test(&dqp->q_pincount)) |
116 | wake_up(&dqp->q_pinwait); | 109 | wake_up(&dqp->q_pinwait); |
117 | } | 110 | } |
118 | 111 | ||
119 | /* ARGSUSED */ | ||
120 | STATIC void | ||
121 | xfs_qm_dquot_logitem_unpin_remove( | ||
122 | xfs_dq_logitem_t *logitem, | ||
123 | xfs_trans_t *tp) | ||
124 | { | ||
125 | xfs_qm_dquot_logitem_unpin(logitem); | ||
126 | } | ||
127 | |||
128 | /* | 112 | /* |
129 | * Given the logitem, this writes the corresponding dquot entry to disk | 113 | * Given the logitem, this writes the corresponding dquot entry to disk |
130 | * asynchronously. This is called with the dquot entry securely locked; | 114 | * asynchronously. This is called with the dquot entry securely locked; |
@@ -133,12 +117,10 @@ xfs_qm_dquot_logitem_unpin_remove( | |||
133 | */ | 117 | */ |
134 | STATIC void | 118 | STATIC void |
135 | xfs_qm_dquot_logitem_push( | 119 | xfs_qm_dquot_logitem_push( |
136 | xfs_dq_logitem_t *logitem) | 120 | struct xfs_log_item *lip) |
137 | { | 121 | { |
138 | xfs_dquot_t *dqp; | 122 | struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; |
139 | int error; | 123 | int error; |
140 | |||
141 | dqp = logitem->qli_dquot; | ||
142 | 124 | ||
143 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 125 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); |
144 | ASSERT(!completion_done(&dqp->q_flush)); | 126 | ASSERT(!completion_done(&dqp->q_flush)); |
@@ -160,27 +142,25 @@ xfs_qm_dquot_logitem_push( | |||
160 | xfs_dqunlock(dqp); | 142 | xfs_dqunlock(dqp); |
161 | } | 143 | } |
162 | 144 | ||
163 | /*ARGSUSED*/ | ||
164 | STATIC xfs_lsn_t | 145 | STATIC xfs_lsn_t |
165 | xfs_qm_dquot_logitem_committed( | 146 | xfs_qm_dquot_logitem_committed( |
166 | xfs_dq_logitem_t *l, | 147 | struct xfs_log_item *lip, |
167 | xfs_lsn_t lsn) | 148 | xfs_lsn_t lsn) |
168 | { | 149 | { |
169 | /* | 150 | /* |
170 | * We always re-log the entire dquot when it becomes dirty, | 151 | * We always re-log the entire dquot when it becomes dirty, |
171 | * so, the latest copy _is_ the only one that matters. | 152 | * so, the latest copy _is_ the only one that matters. |
172 | */ | 153 | */ |
173 | return (lsn); | 154 | return lsn; |
174 | } | 155 | } |
175 | 156 | ||
176 | |||
177 | /* | 157 | /* |
178 | * This is called to wait for the given dquot to be unpinned. | 158 | * This is called to wait for the given dquot to be unpinned. |
179 | * Most of these pin/unpin routines are plagiarized from inode code. | 159 | * Most of these pin/unpin routines are plagiarized from inode code. |
180 | */ | 160 | */ |
181 | void | 161 | void |
182 | xfs_qm_dqunpin_wait( | 162 | xfs_qm_dqunpin_wait( |
183 | xfs_dquot_t *dqp) | 163 | struct xfs_dquot *dqp) |
184 | { | 164 | { |
185 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 165 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); |
186 | if (atomic_read(&dqp->q_pincount) == 0) | 166 | if (atomic_read(&dqp->q_pincount) == 0) |
@@ -206,13 +186,12 @@ xfs_qm_dqunpin_wait( | |||
206 | */ | 186 | */ |
207 | STATIC void | 187 | STATIC void |
208 | xfs_qm_dquot_logitem_pushbuf( | 188 | xfs_qm_dquot_logitem_pushbuf( |
209 | xfs_dq_logitem_t *qip) | 189 | struct xfs_log_item *lip) |
210 | { | 190 | { |
211 | xfs_dquot_t *dqp; | 191 | struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip); |
212 | xfs_mount_t *mp; | 192 | struct xfs_dquot *dqp = qlip->qli_dquot; |
213 | xfs_buf_t *bp; | 193 | struct xfs_buf *bp; |
214 | 194 | ||
215 | dqp = qip->qli_dquot; | ||
216 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 195 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); |
217 | 196 | ||
218 | /* | 197 | /* |
@@ -220,22 +199,20 @@ xfs_qm_dquot_logitem_pushbuf( | |||
220 | * inode flush completed and the inode was taken off the AIL. | 199 | * inode flush completed and the inode was taken off the AIL. |
221 | * So, just get out. | 200 | * So, just get out. |
222 | */ | 201 | */ |
223 | if (completion_done(&dqp->q_flush) || | 202 | if (completion_done(&dqp->q_flush) || |
224 | ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) { | 203 | !(lip->li_flags & XFS_LI_IN_AIL)) { |
225 | xfs_dqunlock(dqp); | 204 | xfs_dqunlock(dqp); |
226 | return; | 205 | return; |
227 | } | 206 | } |
228 | mp = dqp->q_mount; | 207 | |
229 | bp = xfs_incore(mp->m_ddev_targp, qip->qli_format.qlf_blkno, | 208 | bp = xfs_incore(dqp->q_mount->m_ddev_targp, qlip->qli_format.qlf_blkno, |
230 | mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK); | 209 | dqp->q_mount->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK); |
231 | xfs_dqunlock(dqp); | 210 | xfs_dqunlock(dqp); |
232 | if (!bp) | 211 | if (!bp) |
233 | return; | 212 | return; |
234 | if (XFS_BUF_ISDELAYWRITE(bp)) | 213 | if (XFS_BUF_ISDELAYWRITE(bp)) |
235 | xfs_buf_delwri_promote(bp); | 214 | xfs_buf_delwri_promote(bp); |
236 | xfs_buf_relse(bp); | 215 | xfs_buf_relse(bp); |
237 | return; | ||
238 | |||
239 | } | 216 | } |
240 | 217 | ||
241 | /* | 218 | /* |
@@ -250,15 +227,14 @@ xfs_qm_dquot_logitem_pushbuf( | |||
250 | */ | 227 | */ |
251 | STATIC uint | 228 | STATIC uint |
252 | xfs_qm_dquot_logitem_trylock( | 229 | xfs_qm_dquot_logitem_trylock( |
253 | xfs_dq_logitem_t *qip) | 230 | struct xfs_log_item *lip) |
254 | { | 231 | { |
255 | xfs_dquot_t *dqp; | 232 | struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; |
256 | 233 | ||
257 | dqp = qip->qli_dquot; | ||
258 | if (atomic_read(&dqp->q_pincount) > 0) | 234 | if (atomic_read(&dqp->q_pincount) > 0) |
259 | return XFS_ITEM_PINNED; | 235 | return XFS_ITEM_PINNED; |
260 | 236 | ||
261 | if (! xfs_qm_dqlock_nowait(dqp)) | 237 | if (!xfs_qm_dqlock_nowait(dqp)) |
262 | return XFS_ITEM_LOCKED; | 238 | return XFS_ITEM_LOCKED; |
263 | 239 | ||
264 | if (!xfs_dqflock_nowait(dqp)) { | 240 | if (!xfs_dqflock_nowait(dqp)) { |
@@ -269,11 +245,10 @@ xfs_qm_dquot_logitem_trylock( | |||
269 | return XFS_ITEM_PUSHBUF; | 245 | return XFS_ITEM_PUSHBUF; |
270 | } | 246 | } |
271 | 247 | ||
272 | ASSERT(qip->qli_item.li_flags & XFS_LI_IN_AIL); | 248 | ASSERT(lip->li_flags & XFS_LI_IN_AIL); |
273 | return XFS_ITEM_SUCCESS; | 249 | return XFS_ITEM_SUCCESS; |
274 | } | 250 | } |
275 | 251 | ||
276 | |||
277 | /* | 252 | /* |
278 | * Unlock the dquot associated with the log item. | 253 | * Unlock the dquot associated with the log item. |
279 | * Clear the fields of the dquot and dquot log item that | 254 | * Clear the fields of the dquot and dquot log item that |
@@ -282,12 +257,10 @@ xfs_qm_dquot_logitem_trylock( | |||
282 | */ | 257 | */ |
283 | STATIC void | 258 | STATIC void |
284 | xfs_qm_dquot_logitem_unlock( | 259 | xfs_qm_dquot_logitem_unlock( |
285 | xfs_dq_logitem_t *ql) | 260 | struct xfs_log_item *lip) |
286 | { | 261 | { |
287 | xfs_dquot_t *dqp; | 262 | struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; |
288 | 263 | ||
289 | ASSERT(ql != NULL); | ||
290 | dqp = ql->qli_dquot; | ||
291 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 264 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); |
292 | 265 | ||
293 | /* | 266 | /* |
@@ -304,43 +277,32 @@ xfs_qm_dquot_logitem_unlock( | |||
304 | xfs_dqunlock(dqp); | 277 | xfs_dqunlock(dqp); |
305 | } | 278 | } |
306 | 279 | ||
307 | |||
308 | /* | 280 | /* |
309 | * this needs to stamp an lsn into the dquot, I think. | 281 | * this needs to stamp an lsn into the dquot, I think. |
310 | * rpc's that look at user dquot's would then have to | 282 | * rpc's that look at user dquot's would then have to |
311 | * push on the dependency recorded in the dquot | 283 | * push on the dependency recorded in the dquot |
312 | */ | 284 | */ |
313 | /* ARGSUSED */ | ||
314 | STATIC void | 285 | STATIC void |
315 | xfs_qm_dquot_logitem_committing( | 286 | xfs_qm_dquot_logitem_committing( |
316 | xfs_dq_logitem_t *l, | 287 | struct xfs_log_item *lip, |
317 | xfs_lsn_t lsn) | 288 | xfs_lsn_t lsn) |
318 | { | 289 | { |
319 | return; | ||
320 | } | 290 | } |
321 | 291 | ||
322 | |||
323 | /* | 292 | /* |
324 | * This is the ops vector for dquots | 293 | * This is the ops vector for dquots |
325 | */ | 294 | */ |
326 | static struct xfs_item_ops xfs_dquot_item_ops = { | 295 | static struct xfs_item_ops xfs_dquot_item_ops = { |
327 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_size, | 296 | .iop_size = xfs_qm_dquot_logitem_size, |
328 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 297 | .iop_format = xfs_qm_dquot_logitem_format, |
329 | xfs_qm_dquot_logitem_format, | 298 | .iop_pin = xfs_qm_dquot_logitem_pin, |
330 | .iop_pin = (void(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_pin, | 299 | .iop_unpin = xfs_qm_dquot_logitem_unpin, |
331 | .iop_unpin = (void(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_unpin, | 300 | .iop_trylock = xfs_qm_dquot_logitem_trylock, |
332 | .iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t*)) | 301 | .iop_unlock = xfs_qm_dquot_logitem_unlock, |
333 | xfs_qm_dquot_logitem_unpin_remove, | 302 | .iop_committed = xfs_qm_dquot_logitem_committed, |
334 | .iop_trylock = (uint(*)(xfs_log_item_t*)) | 303 | .iop_push = xfs_qm_dquot_logitem_push, |
335 | xfs_qm_dquot_logitem_trylock, | 304 | .iop_pushbuf = xfs_qm_dquot_logitem_pushbuf, |
336 | .iop_unlock = (void(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_unlock, | 305 | .iop_committing = xfs_qm_dquot_logitem_committing |
337 | .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
338 | xfs_qm_dquot_logitem_committed, | ||
339 | .iop_push = (void(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_push, | ||
340 | .iop_pushbuf = (void(*)(xfs_log_item_t*)) | ||
341 | xfs_qm_dquot_logitem_pushbuf, | ||
342 | .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
343 | xfs_qm_dquot_logitem_committing | ||
344 | }; | 306 | }; |
345 | 307 | ||
346 | /* | 308 | /* |
@@ -350,10 +312,9 @@ static struct xfs_item_ops xfs_dquot_item_ops = { | |||
350 | */ | 312 | */ |
351 | void | 313 | void |
352 | xfs_qm_dquot_logitem_init( | 314 | xfs_qm_dquot_logitem_init( |
353 | struct xfs_dquot *dqp) | 315 | struct xfs_dquot *dqp) |
354 | { | 316 | { |
355 | xfs_dq_logitem_t *lp; | 317 | struct xfs_dq_logitem *lp = &dqp->q_logitem; |
356 | lp = &dqp->q_logitem; | ||
357 | 318 | ||
358 | xfs_log_item_init(dqp->q_mount, &lp->qli_item, XFS_LI_DQUOT, | 319 | xfs_log_item_init(dqp->q_mount, &lp->qli_item, XFS_LI_DQUOT, |
359 | &xfs_dquot_item_ops); | 320 | &xfs_dquot_item_ops); |
@@ -374,16 +335,22 @@ xfs_qm_dquot_logitem_init( | |||
374 | 335 | ||
375 | /*------------------ QUOTAOFF LOG ITEMS -------------------*/ | 336 | /*------------------ QUOTAOFF LOG ITEMS -------------------*/ |
376 | 337 | ||
338 | static inline struct xfs_qoff_logitem *QOFF_ITEM(struct xfs_log_item *lip) | ||
339 | { | ||
340 | return container_of(lip, struct xfs_qoff_logitem, qql_item); | ||
341 | } | ||
342 | |||
343 | |||
377 | /* | 344 | /* |
378 | * This returns the number of iovecs needed to log the given quotaoff item. | 345 | * This returns the number of iovecs needed to log the given quotaoff item. |
379 | * We only need 1 iovec for an quotaoff item. It just logs the | 346 | * We only need 1 iovec for an quotaoff item. It just logs the |
380 | * quotaoff_log_format structure. | 347 | * quotaoff_log_format structure. |
381 | */ | 348 | */ |
382 | /*ARGSUSED*/ | ||
383 | STATIC uint | 349 | STATIC uint |
384 | xfs_qm_qoff_logitem_size(xfs_qoff_logitem_t *qf) | 350 | xfs_qm_qoff_logitem_size( |
351 | struct xfs_log_item *lip) | ||
385 | { | 352 | { |
386 | return (1); | 353 | return 1; |
387 | } | 354 | } |
388 | 355 | ||
389 | /* | 356 | /* |
@@ -394,53 +361,46 @@ xfs_qm_qoff_logitem_size(xfs_qoff_logitem_t *qf) | |||
394 | * slots in the quotaoff item have been filled. | 361 | * slots in the quotaoff item have been filled. |
395 | */ | 362 | */ |
396 | STATIC void | 363 | STATIC void |
397 | xfs_qm_qoff_logitem_format(xfs_qoff_logitem_t *qf, | 364 | xfs_qm_qoff_logitem_format( |
398 | xfs_log_iovec_t *log_vector) | 365 | struct xfs_log_item *lip, |
366 | struct xfs_log_iovec *log_vector) | ||
399 | { | 367 | { |
400 | ASSERT(qf->qql_format.qf_type == XFS_LI_QUOTAOFF); | 368 | struct xfs_qoff_logitem *qflip = QOFF_ITEM(lip); |
369 | |||
370 | ASSERT(qflip->qql_format.qf_type == XFS_LI_QUOTAOFF); | ||
401 | 371 | ||
402 | log_vector->i_addr = (xfs_caddr_t)&(qf->qql_format); | 372 | log_vector->i_addr = &qflip->qql_format; |
403 | log_vector->i_len = sizeof(xfs_qoff_logitem_t); | 373 | log_vector->i_len = sizeof(xfs_qoff_logitem_t); |
404 | log_vector->i_type = XLOG_REG_TYPE_QUOTAOFF; | 374 | log_vector->i_type = XLOG_REG_TYPE_QUOTAOFF; |
405 | qf->qql_format.qf_size = 1; | 375 | qflip->qql_format.qf_size = 1; |
406 | } | 376 | } |
407 | 377 | ||
408 | |||
409 | /* | 378 | /* |
410 | * Pinning has no meaning for an quotaoff item, so just return. | 379 | * Pinning has no meaning for an quotaoff item, so just return. |
411 | */ | 380 | */ |
412 | /*ARGSUSED*/ | ||
413 | STATIC void | 381 | STATIC void |
414 | xfs_qm_qoff_logitem_pin(xfs_qoff_logitem_t *qf) | 382 | xfs_qm_qoff_logitem_pin( |
383 | struct xfs_log_item *lip) | ||
415 | { | 384 | { |
416 | return; | ||
417 | } | 385 | } |
418 | 386 | ||
419 | |||
420 | /* | 387 | /* |
421 | * Since pinning has no meaning for an quotaoff item, unpinning does | 388 | * Since pinning has no meaning for an quotaoff item, unpinning does |
422 | * not either. | 389 | * not either. |
423 | */ | 390 | */ |
424 | /*ARGSUSED*/ | ||
425 | STATIC void | 391 | STATIC void |
426 | xfs_qm_qoff_logitem_unpin(xfs_qoff_logitem_t *qf) | 392 | xfs_qm_qoff_logitem_unpin( |
393 | struct xfs_log_item *lip, | ||
394 | int remove) | ||
427 | { | 395 | { |
428 | return; | ||
429 | } | ||
430 | |||
431 | /*ARGSUSED*/ | ||
432 | STATIC void | ||
433 | xfs_qm_qoff_logitem_unpin_remove(xfs_qoff_logitem_t *qf, xfs_trans_t *tp) | ||
434 | { | ||
435 | return; | ||
436 | } | 396 | } |
437 | 397 | ||
438 | /* | 398 | /* |
439 | * Quotaoff items have no locking, so just return success. | 399 | * Quotaoff items have no locking, so just return success. |
440 | */ | 400 | */ |
441 | /*ARGSUSED*/ | ||
442 | STATIC uint | 401 | STATIC uint |
443 | xfs_qm_qoff_logitem_trylock(xfs_qoff_logitem_t *qf) | 402 | xfs_qm_qoff_logitem_trylock( |
403 | struct xfs_log_item *lip) | ||
444 | { | 404 | { |
445 | return XFS_ITEM_LOCKED; | 405 | return XFS_ITEM_LOCKED; |
446 | } | 406 | } |
@@ -449,53 +409,51 @@ xfs_qm_qoff_logitem_trylock(xfs_qoff_logitem_t *qf) | |||
449 | * Quotaoff items have no locking or pushing, so return failure | 409 | * Quotaoff items have no locking or pushing, so return failure |
450 | * so that the caller doesn't bother with us. | 410 | * so that the caller doesn't bother with us. |
451 | */ | 411 | */ |
452 | /*ARGSUSED*/ | ||
453 | STATIC void | 412 | STATIC void |
454 | xfs_qm_qoff_logitem_unlock(xfs_qoff_logitem_t *qf) | 413 | xfs_qm_qoff_logitem_unlock( |
414 | struct xfs_log_item *lip) | ||
455 | { | 415 | { |
456 | return; | ||
457 | } | 416 | } |
458 | 417 | ||
459 | /* | 418 | /* |
460 | * The quotaoff-start-item is logged only once and cannot be moved in the log, | 419 | * The quotaoff-start-item is logged only once and cannot be moved in the log, |
461 | * so simply return the lsn at which it's been logged. | 420 | * so simply return the lsn at which it's been logged. |
462 | */ | 421 | */ |
463 | /*ARGSUSED*/ | ||
464 | STATIC xfs_lsn_t | 422 | STATIC xfs_lsn_t |
465 | xfs_qm_qoff_logitem_committed(xfs_qoff_logitem_t *qf, xfs_lsn_t lsn) | 423 | xfs_qm_qoff_logitem_committed( |
424 | struct xfs_log_item *lip, | ||
425 | xfs_lsn_t lsn) | ||
466 | { | 426 | { |
467 | return (lsn); | 427 | return lsn; |
468 | } | 428 | } |
469 | 429 | ||
470 | /* | 430 | /* |
471 | * There isn't much you can do to push on an quotaoff item. It is simply | 431 | * There isn't much you can do to push on an quotaoff item. It is simply |
472 | * stuck waiting for the log to be flushed to disk. | 432 | * stuck waiting for the log to be flushed to disk. |
473 | */ | 433 | */ |
474 | /*ARGSUSED*/ | ||
475 | STATIC void | 434 | STATIC void |
476 | xfs_qm_qoff_logitem_push(xfs_qoff_logitem_t *qf) | 435 | xfs_qm_qoff_logitem_push( |
436 | struct xfs_log_item *lip) | ||
477 | { | 437 | { |
478 | return; | ||
479 | } | 438 | } |
480 | 439 | ||
481 | 440 | ||
482 | /*ARGSUSED*/ | ||
483 | STATIC xfs_lsn_t | 441 | STATIC xfs_lsn_t |
484 | xfs_qm_qoffend_logitem_committed( | 442 | xfs_qm_qoffend_logitem_committed( |
485 | xfs_qoff_logitem_t *qfe, | 443 | struct xfs_log_item *lip, |
486 | xfs_lsn_t lsn) | 444 | xfs_lsn_t lsn) |
487 | { | 445 | { |
488 | xfs_qoff_logitem_t *qfs; | 446 | struct xfs_qoff_logitem *qfe = QOFF_ITEM(lip); |
489 | struct xfs_ail *ailp; | 447 | struct xfs_qoff_logitem *qfs = qfe->qql_start_lip; |
448 | struct xfs_ail *ailp = qfs->qql_item.li_ailp; | ||
490 | 449 | ||
491 | qfs = qfe->qql_start_lip; | ||
492 | ailp = qfs->qql_item.li_ailp; | ||
493 | spin_lock(&ailp->xa_lock); | ||
494 | /* | 450 | /* |
495 | * Delete the qoff-start logitem from the AIL. | 451 | * Delete the qoff-start logitem from the AIL. |
496 | * xfs_trans_ail_delete() drops the AIL lock. | 452 | * xfs_trans_ail_delete() drops the AIL lock. |
497 | */ | 453 | */ |
454 | spin_lock(&ailp->xa_lock); | ||
498 | xfs_trans_ail_delete(ailp, (xfs_log_item_t *)qfs); | 455 | xfs_trans_ail_delete(ailp, (xfs_log_item_t *)qfs); |
456 | |||
499 | kmem_free(qfs); | 457 | kmem_free(qfs); |
500 | kmem_free(qfe); | 458 | kmem_free(qfe); |
501 | return (xfs_lsn_t)-1; | 459 | return (xfs_lsn_t)-1; |
@@ -515,71 +473,52 @@ xfs_qm_qoffend_logitem_committed( | |||
515 | * (truly makes the quotaoff irrevocable). If we do something else, | 473 | * (truly makes the quotaoff irrevocable). If we do something else, |
516 | * then maybe we don't need two. | 474 | * then maybe we don't need two. |
517 | */ | 475 | */ |
518 | /* ARGSUSED */ | ||
519 | STATIC void | ||
520 | xfs_qm_qoff_logitem_committing(xfs_qoff_logitem_t *qip, xfs_lsn_t commit_lsn) | ||
521 | { | ||
522 | return; | ||
523 | } | ||
524 | |||
525 | /* ARGSUSED */ | ||
526 | STATIC void | 476 | STATIC void |
527 | xfs_qm_qoffend_logitem_committing(xfs_qoff_logitem_t *qip, xfs_lsn_t commit_lsn) | 477 | xfs_qm_qoff_logitem_committing( |
478 | struct xfs_log_item *lip, | ||
479 | xfs_lsn_t commit_lsn) | ||
528 | { | 480 | { |
529 | return; | ||
530 | } | 481 | } |
531 | 482 | ||
532 | static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { | 483 | static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { |
533 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size, | 484 | .iop_size = xfs_qm_qoff_logitem_size, |
534 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 485 | .iop_format = xfs_qm_qoff_logitem_format, |
535 | xfs_qm_qoff_logitem_format, | 486 | .iop_pin = xfs_qm_qoff_logitem_pin, |
536 | .iop_pin = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_pin, | 487 | .iop_unpin = xfs_qm_qoff_logitem_unpin, |
537 | .iop_unpin = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_unpin, | 488 | .iop_trylock = xfs_qm_qoff_logitem_trylock, |
538 | .iop_unpin_remove = (void(*)(xfs_log_item_t*,xfs_trans_t*)) | 489 | .iop_unlock = xfs_qm_qoff_logitem_unlock, |
539 | xfs_qm_qoff_logitem_unpin_remove, | 490 | .iop_committed = xfs_qm_qoffend_logitem_committed, |
540 | .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_trylock, | 491 | .iop_push = xfs_qm_qoff_logitem_push, |
541 | .iop_unlock = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_unlock, | 492 | .iop_committing = xfs_qm_qoff_logitem_committing |
542 | .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
543 | xfs_qm_qoffend_logitem_committed, | ||
544 | .iop_push = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_push, | ||
545 | .iop_pushbuf = NULL, | ||
546 | .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
547 | xfs_qm_qoffend_logitem_committing | ||
548 | }; | 493 | }; |
549 | 494 | ||
550 | /* | 495 | /* |
551 | * This is the ops vector shared by all quotaoff-start log items. | 496 | * This is the ops vector shared by all quotaoff-start log items. |
552 | */ | 497 | */ |
553 | static struct xfs_item_ops xfs_qm_qoff_logitem_ops = { | 498 | static struct xfs_item_ops xfs_qm_qoff_logitem_ops = { |
554 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size, | 499 | .iop_size = xfs_qm_qoff_logitem_size, |
555 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 500 | .iop_format = xfs_qm_qoff_logitem_format, |
556 | xfs_qm_qoff_logitem_format, | 501 | .iop_pin = xfs_qm_qoff_logitem_pin, |
557 | .iop_pin = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_pin, | 502 | .iop_unpin = xfs_qm_qoff_logitem_unpin, |
558 | .iop_unpin = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_unpin, | 503 | .iop_trylock = xfs_qm_qoff_logitem_trylock, |
559 | .iop_unpin_remove = (void(*)(xfs_log_item_t*,xfs_trans_t*)) | 504 | .iop_unlock = xfs_qm_qoff_logitem_unlock, |
560 | xfs_qm_qoff_logitem_unpin_remove, | 505 | .iop_committed = xfs_qm_qoff_logitem_committed, |
561 | .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_trylock, | 506 | .iop_push = xfs_qm_qoff_logitem_push, |
562 | .iop_unlock = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_unlock, | 507 | .iop_committing = xfs_qm_qoff_logitem_committing |
563 | .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
564 | xfs_qm_qoff_logitem_committed, | ||
565 | .iop_push = (void(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_push, | ||
566 | .iop_pushbuf = NULL, | ||
567 | .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
568 | xfs_qm_qoff_logitem_committing | ||
569 | }; | 508 | }; |
570 | 509 | ||
571 | /* | 510 | /* |
572 | * Allocate and initialize an quotaoff item of the correct quota type(s). | 511 | * Allocate and initialize an quotaoff item of the correct quota type(s). |
573 | */ | 512 | */ |
574 | xfs_qoff_logitem_t * | 513 | struct xfs_qoff_logitem * |
575 | xfs_qm_qoff_logitem_init( | 514 | xfs_qm_qoff_logitem_init( |
576 | struct xfs_mount *mp, | 515 | struct xfs_mount *mp, |
577 | xfs_qoff_logitem_t *start, | 516 | struct xfs_qoff_logitem *start, |
578 | uint flags) | 517 | uint flags) |
579 | { | 518 | { |
580 | xfs_qoff_logitem_t *qf; | 519 | struct xfs_qoff_logitem *qf; |
581 | 520 | ||
582 | qf = (xfs_qoff_logitem_t*) kmem_zalloc(sizeof(xfs_qoff_logitem_t), KM_SLEEP); | 521 | qf = kmem_zalloc(sizeof(struct xfs_qoff_logitem), KM_SLEEP); |
583 | 522 | ||
584 | xfs_log_item_init(mp, &qf->qql_item, XFS_LI_QUOTAOFF, start ? | 523 | xfs_log_item_init(mp, &qf->qql_item, XFS_LI_QUOTAOFF, start ? |
585 | &xfs_qm_qoffend_logitem_ops : &xfs_qm_qoff_logitem_ops); | 524 | &xfs_qm_qoffend_logitem_ops : &xfs_qm_qoff_logitem_ops); |
@@ -587,5 +526,5 @@ xfs_qm_qoff_logitem_init( | |||
587 | qf->qql_format.qf_type = XFS_LI_QUOTAOFF; | 526 | qf->qql_format.qf_type = XFS_LI_QUOTAOFF; |
588 | qf->qql_format.qf_flags = flags; | 527 | qf->qql_format.qf_flags = flags; |
589 | qf->qql_start_lip = start; | 528 | qf->qql_start_lip = start; |
590 | return (qf); | 529 | return qf; |
591 | } | 530 | } |
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 8c117ff2e3ab..9a92407109a1 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -23,25 +23,18 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | ||
27 | #include "xfs_alloc.h" | 26 | #include "xfs_alloc.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_quota.h" | 27 | #include "xfs_quota.h" |
30 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | ||
33 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
37 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
38 | #include "xfs_btree.h" | ||
39 | #include "xfs_ialloc.h" | 33 | #include "xfs_ialloc.h" |
40 | #include "xfs_itable.h" | 34 | #include "xfs_itable.h" |
41 | #include "xfs_rtalloc.h" | 35 | #include "xfs_rtalloc.h" |
42 | #include "xfs_error.h" | 36 | #include "xfs_error.h" |
43 | #include "xfs_bmap.h" | 37 | #include "xfs_bmap.h" |
44 | #include "xfs_rw.h" | ||
45 | #include "xfs_attr.h" | 38 | #include "xfs_attr.h" |
46 | #include "xfs_buf_item.h" | 39 | #include "xfs_buf_item.h" |
47 | #include "xfs_trans_space.h" | 40 | #include "xfs_trans_space.h" |
@@ -69,7 +62,7 @@ STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); | |||
69 | 62 | ||
70 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); | 63 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); |
71 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); | 64 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); |
72 | STATIC int xfs_qm_shake(int, gfp_t); | 65 | STATIC int xfs_qm_shake(struct shrinker *, int, gfp_t); |
73 | 66 | ||
74 | static struct shrinker xfs_qm_shaker = { | 67 | static struct shrinker xfs_qm_shaker = { |
75 | .shrink = xfs_qm_shake, | 68 | .shrink = xfs_qm_shake, |
@@ -1497,7 +1490,7 @@ xfs_qm_dqiterate( | |||
1497 | maxlblkcnt - lblkno, | 1490 | maxlblkcnt - lblkno, |
1498 | XFS_BMAPI_METADATA, | 1491 | XFS_BMAPI_METADATA, |
1499 | NULL, | 1492 | NULL, |
1500 | 0, map, &nmaps, NULL, NULL); | 1493 | 0, map, &nmaps, NULL); |
1501 | xfs_iunlock(qip, XFS_ILOCK_SHARED); | 1494 | xfs_iunlock(qip, XFS_ILOCK_SHARED); |
1502 | if (error) | 1495 | if (error) |
1503 | break; | 1496 | break; |
@@ -1669,7 +1662,8 @@ xfs_qm_dqusage_adjust( | |||
1669 | * making us disable quotas for the file system. | 1662 | * making us disable quotas for the file system. |
1670 | */ | 1663 | */ |
1671 | if ((error = xfs_qm_dqget_noattach(ip, &udqp, &gdqp))) { | 1664 | if ((error = xfs_qm_dqget_noattach(ip, &udqp, &gdqp))) { |
1672 | xfs_iput(ip, XFS_ILOCK_EXCL); | 1665 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
1666 | IRELE(ip); | ||
1673 | *res = BULKSTAT_RV_GIVEUP; | 1667 | *res = BULKSTAT_RV_GIVEUP; |
1674 | return error; | 1668 | return error; |
1675 | } | 1669 | } |
@@ -1682,7 +1676,8 @@ xfs_qm_dqusage_adjust( | |||
1682 | * Walk thru the extent list and count the realtime blocks. | 1676 | * Walk thru the extent list and count the realtime blocks. |
1683 | */ | 1677 | */ |
1684 | if ((error = xfs_qm_get_rtblks(ip, &rtblks))) { | 1678 | if ((error = xfs_qm_get_rtblks(ip, &rtblks))) { |
1685 | xfs_iput(ip, XFS_ILOCK_EXCL); | 1679 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
1680 | IRELE(ip); | ||
1686 | if (udqp) | 1681 | if (udqp) |
1687 | xfs_qm_dqput(udqp); | 1682 | xfs_qm_dqput(udqp); |
1688 | if (gdqp) | 1683 | if (gdqp) |
@@ -2117,7 +2112,10 @@ xfs_qm_shake_freelist( | |||
2117 | */ | 2112 | */ |
2118 | /* ARGSUSED */ | 2113 | /* ARGSUSED */ |
2119 | STATIC int | 2114 | STATIC int |
2120 | xfs_qm_shake(int nr_to_scan, gfp_t gfp_mask) | 2115 | xfs_qm_shake( |
2116 | struct shrinker *shrink, | ||
2117 | int nr_to_scan, | ||
2118 | gfp_t gfp_mask) | ||
2121 | { | 2119 | { |
2122 | int ndqused, nfree, n; | 2120 | int ndqused, nfree, n; |
2123 | 2121 | ||
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index 97b410c12794..bea02d786c5d 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c | |||
@@ -23,25 +23,15 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | ||
27 | #include "xfs_alloc.h" | 26 | #include "xfs_alloc.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_quota.h" | 27 | #include "xfs_quota.h" |
30 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | ||
33 | #include "xfs_ialloc_btree.h" | ||
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | ||
37 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
38 | #include "xfs_ialloc.h" | ||
39 | #include "xfs_itable.h" | 31 | #include "xfs_itable.h" |
40 | #include "xfs_btree.h" | ||
41 | #include "xfs_bmap.h" | 32 | #include "xfs_bmap.h" |
42 | #include "xfs_rtalloc.h" | 33 | #include "xfs_rtalloc.h" |
43 | #include "xfs_error.h" | 34 | #include "xfs_error.h" |
44 | #include "xfs_rw.h" | ||
45 | #include "xfs_attr.h" | 35 | #include "xfs_attr.h" |
46 | #include "xfs_buf_item.h" | 36 | #include "xfs_buf_item.h" |
47 | #include "xfs_qm.h" | 37 | #include "xfs_qm.h" |
diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c index 3d1fc79532e2..8671a0b32644 100644 --- a/fs/xfs/quota/xfs_qm_stats.c +++ b/fs/xfs/quota/xfs_qm_stats.c | |||
@@ -23,25 +23,15 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | ||
27 | #include "xfs_alloc.h" | 26 | #include "xfs_alloc.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_quota.h" | 27 | #include "xfs_quota.h" |
30 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | ||
33 | #include "xfs_ialloc_btree.h" | ||
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | ||
37 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
38 | #include "xfs_ialloc.h" | ||
39 | #include "xfs_itable.h" | 31 | #include "xfs_itable.h" |
40 | #include "xfs_bmap.h" | 32 | #include "xfs_bmap.h" |
41 | #include "xfs_btree.h" | ||
42 | #include "xfs_rtalloc.h" | 33 | #include "xfs_rtalloc.h" |
43 | #include "xfs_error.h" | 34 | #include "xfs_error.h" |
44 | #include "xfs_rw.h" | ||
45 | #include "xfs_attr.h" | 35 | #include "xfs_attr.h" |
46 | #include "xfs_buf_item.h" | 36 | #include "xfs_buf_item.h" |
47 | #include "xfs_qm.h" | 37 | #include "xfs_qm.h" |
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index b4487764e923..45e5849df238 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c | |||
@@ -26,25 +26,15 @@ | |||
26 | #include "xfs_trans.h" | 26 | #include "xfs_trans.h" |
27 | #include "xfs_sb.h" | 27 | #include "xfs_sb.h" |
28 | #include "xfs_ag.h" | 28 | #include "xfs_ag.h" |
29 | #include "xfs_dir2.h" | ||
30 | #include "xfs_alloc.h" | 29 | #include "xfs_alloc.h" |
31 | #include "xfs_dmapi.h" | ||
32 | #include "xfs_quota.h" | 30 | #include "xfs_quota.h" |
33 | #include "xfs_mount.h" | 31 | #include "xfs_mount.h" |
34 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
35 | #include "xfs_alloc_btree.h" | ||
36 | #include "xfs_ialloc_btree.h" | ||
37 | #include "xfs_dir2_sf.h" | ||
38 | #include "xfs_attr_sf.h" | ||
39 | #include "xfs_dinode.h" | ||
40 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
41 | #include "xfs_ialloc.h" | ||
42 | #include "xfs_itable.h" | 34 | #include "xfs_itable.h" |
43 | #include "xfs_bmap.h" | 35 | #include "xfs_bmap.h" |
44 | #include "xfs_btree.h" | ||
45 | #include "xfs_rtalloc.h" | 36 | #include "xfs_rtalloc.h" |
46 | #include "xfs_error.h" | 37 | #include "xfs_error.h" |
47 | #include "xfs_rw.h" | ||
48 | #include "xfs_attr.h" | 38 | #include "xfs_attr.h" |
49 | #include "xfs_buf_item.h" | 39 | #include "xfs_buf_item.h" |
50 | #include "xfs_utils.h" | 40 | #include "xfs_utils.h" |
@@ -248,40 +238,74 @@ out_unlock: | |||
248 | return error; | 238 | return error; |
249 | } | 239 | } |
250 | 240 | ||
241 | STATIC int | ||
242 | xfs_qm_scall_trunc_qfile( | ||
243 | struct xfs_mount *mp, | ||
244 | xfs_ino_t ino) | ||
245 | { | ||
246 | struct xfs_inode *ip; | ||
247 | struct xfs_trans *tp; | ||
248 | int error; | ||
249 | |||
250 | if (ino == NULLFSINO) | ||
251 | return 0; | ||
252 | |||
253 | error = xfs_iget(mp, NULL, ino, 0, 0, &ip); | ||
254 | if (error) | ||
255 | return error; | ||
256 | |||
257 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | ||
258 | |||
259 | tp = xfs_trans_alloc(mp, XFS_TRANS_TRUNCATE_FILE); | ||
260 | error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, | ||
261 | XFS_TRANS_PERM_LOG_RES, | ||
262 | XFS_ITRUNCATE_LOG_COUNT); | ||
263 | if (error) { | ||
264 | xfs_trans_cancel(tp, 0); | ||
265 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
266 | goto out_put; | ||
267 | } | ||
268 | |||
269 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
270 | xfs_trans_ijoin(tp, ip); | ||
271 | |||
272 | error = xfs_itruncate_finish(&tp, ip, 0, XFS_DATA_FORK, 1); | ||
273 | if (error) { | ||
274 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | | ||
275 | XFS_TRANS_ABORT); | ||
276 | goto out_unlock; | ||
277 | } | ||
278 | |||
279 | xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
280 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | ||
281 | |||
282 | out_unlock: | ||
283 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
284 | out_put: | ||
285 | IRELE(ip); | ||
286 | return error; | ||
287 | } | ||
288 | |||
251 | int | 289 | int |
252 | xfs_qm_scall_trunc_qfiles( | 290 | xfs_qm_scall_trunc_qfiles( |
253 | xfs_mount_t *mp, | 291 | xfs_mount_t *mp, |
254 | uint flags) | 292 | uint flags) |
255 | { | 293 | { |
256 | int error = 0, error2 = 0; | 294 | int error = 0, error2 = 0; |
257 | xfs_inode_t *qip; | ||
258 | 295 | ||
259 | if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { | 296 | if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { |
260 | qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags); | 297 | qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags); |
261 | return XFS_ERROR(EINVAL); | 298 | return XFS_ERROR(EINVAL); |
262 | } | 299 | } |
263 | 300 | ||
264 | if ((flags & XFS_DQ_USER) && mp->m_sb.sb_uquotino != NULLFSINO) { | 301 | if (flags & XFS_DQ_USER) |
265 | error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip); | 302 | error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino); |
266 | if (!error) { | 303 | if (flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) |
267 | error = xfs_truncate_file(mp, qip); | 304 | error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino); |
268 | IRELE(qip); | ||
269 | } | ||
270 | } | ||
271 | |||
272 | if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) && | ||
273 | mp->m_sb.sb_gquotino != NULLFSINO) { | ||
274 | error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip); | ||
275 | if (!error2) { | ||
276 | error2 = xfs_truncate_file(mp, qip); | ||
277 | IRELE(qip); | ||
278 | } | ||
279 | } | ||
280 | 305 | ||
281 | return error ? error : error2; | 306 | return error ? error : error2; |
282 | } | 307 | } |
283 | 308 | ||
284 | |||
285 | /* | 309 | /* |
286 | * Switch on (a given) quota enforcement for a filesystem. This takes | 310 | * Switch on (a given) quota enforcement for a filesystem. This takes |
287 | * effect immediately. | 311 | * effect immediately. |
@@ -786,9 +810,9 @@ xfs_qm_export_dquot( | |||
786 | } | 810 | } |
787 | 811 | ||
788 | #ifdef DEBUG | 812 | #ifdef DEBUG |
789 | if (((XFS_IS_UQUOTA_ENFORCED(mp) && dst->d_flags == XFS_USER_QUOTA) || | 813 | if (((XFS_IS_UQUOTA_ENFORCED(mp) && dst->d_flags == FS_USER_QUOTA) || |
790 | (XFS_IS_OQUOTA_ENFORCED(mp) && | 814 | (XFS_IS_OQUOTA_ENFORCED(mp) && |
791 | (dst->d_flags & (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA)))) && | 815 | (dst->d_flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)))) && |
792 | dst->d_id != 0) { | 816 | dst->d_id != 0) { |
793 | if (((int) dst->d_bcount >= (int) dst->d_blk_softlimit) && | 817 | if (((int) dst->d_bcount >= (int) dst->d_blk_softlimit) && |
794 | (dst->d_blk_softlimit > 0)) { | 818 | (dst->d_blk_softlimit > 0)) { |
@@ -809,17 +833,17 @@ xfs_qm_export_qtype_flags( | |||
809 | /* | 833 | /* |
810 | * Can't be more than one, or none. | 834 | * Can't be more than one, or none. |
811 | */ | 835 | */ |
812 | ASSERT((flags & (XFS_PROJ_QUOTA | XFS_USER_QUOTA)) != | 836 | ASSERT((flags & (FS_PROJ_QUOTA | FS_USER_QUOTA)) != |
813 | (XFS_PROJ_QUOTA | XFS_USER_QUOTA)); | 837 | (FS_PROJ_QUOTA | FS_USER_QUOTA)); |
814 | ASSERT((flags & (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA)) != | 838 | ASSERT((flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)) != |
815 | (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA)); | 839 | (FS_PROJ_QUOTA | FS_GROUP_QUOTA)); |
816 | ASSERT((flags & (XFS_USER_QUOTA | XFS_GROUP_QUOTA)) != | 840 | ASSERT((flags & (FS_USER_QUOTA | FS_GROUP_QUOTA)) != |
817 | (XFS_USER_QUOTA | XFS_GROUP_QUOTA)); | 841 | (FS_USER_QUOTA | FS_GROUP_QUOTA)); |
818 | ASSERT((flags & (XFS_PROJ_QUOTA|XFS_USER_QUOTA|XFS_GROUP_QUOTA)) != 0); | 842 | ASSERT((flags & (FS_PROJ_QUOTA|FS_USER_QUOTA|FS_GROUP_QUOTA)) != 0); |
819 | 843 | ||
820 | return (flags & XFS_DQ_USER) ? | 844 | return (flags & XFS_DQ_USER) ? |
821 | XFS_USER_QUOTA : (flags & XFS_DQ_PROJ) ? | 845 | FS_USER_QUOTA : (flags & XFS_DQ_PROJ) ? |
822 | XFS_PROJ_QUOTA : XFS_GROUP_QUOTA; | 846 | FS_PROJ_QUOTA : FS_GROUP_QUOTA; |
823 | } | 847 | } |
824 | 848 | ||
825 | STATIC uint | 849 | STATIC uint |
@@ -830,16 +854,16 @@ xfs_qm_export_flags( | |||
830 | 854 | ||
831 | uflags = 0; | 855 | uflags = 0; |
832 | if (flags & XFS_UQUOTA_ACCT) | 856 | if (flags & XFS_UQUOTA_ACCT) |
833 | uflags |= XFS_QUOTA_UDQ_ACCT; | 857 | uflags |= FS_QUOTA_UDQ_ACCT; |
834 | if (flags & XFS_PQUOTA_ACCT) | 858 | if (flags & XFS_PQUOTA_ACCT) |
835 | uflags |= XFS_QUOTA_PDQ_ACCT; | 859 | uflags |= FS_QUOTA_PDQ_ACCT; |
836 | if (flags & XFS_GQUOTA_ACCT) | 860 | if (flags & XFS_GQUOTA_ACCT) |
837 | uflags |= XFS_QUOTA_GDQ_ACCT; | 861 | uflags |= FS_QUOTA_GDQ_ACCT; |
838 | if (flags & XFS_UQUOTA_ENFD) | 862 | if (flags & XFS_UQUOTA_ENFD) |
839 | uflags |= XFS_QUOTA_UDQ_ENFD; | 863 | uflags |= FS_QUOTA_UDQ_ENFD; |
840 | if (flags & (XFS_OQUOTA_ENFD)) { | 864 | if (flags & (XFS_OQUOTA_ENFD)) { |
841 | uflags |= (flags & XFS_GQUOTA_ACCT) ? | 865 | uflags |= (flags & XFS_GQUOTA_ACCT) ? |
842 | XFS_QUOTA_GDQ_ENFD : XFS_QUOTA_PDQ_ENFD; | 866 | FS_QUOTA_GDQ_ENFD : FS_QUOTA_PDQ_ENFD; |
843 | } | 867 | } |
844 | return (uflags); | 868 | return (uflags); |
845 | } | 869 | } |
@@ -875,8 +899,9 @@ xfs_dqrele_inode( | |||
875 | xfs_qm_dqrele(ip->i_gdquot); | 899 | xfs_qm_dqrele(ip->i_gdquot); |
876 | ip->i_gdquot = NULL; | 900 | ip->i_gdquot = NULL; |
877 | } | 901 | } |
878 | xfs_iput(ip, XFS_ILOCK_EXCL); | 902 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
879 | 903 | ||
904 | IRELE(ip); | ||
880 | return 0; | 905 | return 0; |
881 | } | 906 | } |
882 | 907 | ||
@@ -1143,7 +1168,8 @@ xfs_qm_internalqcheck_adjust( | |||
1143 | * of those now. | 1168 | * of those now. |
1144 | */ | 1169 | */ |
1145 | if (! ipreleased) { | 1170 | if (! ipreleased) { |
1146 | xfs_iput(ip, lock_flags); | 1171 | xfs_iunlock(ip, lock_flags); |
1172 | IRELE(ip); | ||
1147 | ipreleased = B_TRUE; | 1173 | ipreleased = B_TRUE; |
1148 | goto again; | 1174 | goto again; |
1149 | } | 1175 | } |
@@ -1160,7 +1186,8 @@ xfs_qm_internalqcheck_adjust( | |||
1160 | ASSERT(gd); | 1186 | ASSERT(gd); |
1161 | xfs_qm_internalqcheck_dqadjust(ip, gd); | 1187 | xfs_qm_internalqcheck_dqadjust(ip, gd); |
1162 | } | 1188 | } |
1163 | xfs_iput(ip, lock_flags); | 1189 | xfs_iunlock(ip, lock_flags); |
1190 | IRELE(ip); | ||
1164 | *res = BULKSTAT_RV_DIDONE; | 1191 | *res = BULKSTAT_RV_DIDONE; |
1165 | return (0); | 1192 | return (0); |
1166 | } | 1193 | } |
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index 061d827da33c..7de91d1b75c0 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c | |||
@@ -23,25 +23,15 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | ||
27 | #include "xfs_alloc.h" | 26 | #include "xfs_alloc.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_quota.h" | 27 | #include "xfs_quota.h" |
30 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | ||
33 | #include "xfs_ialloc_btree.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | ||
36 | #include "xfs_dinode.h" | ||
37 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
38 | #include "xfs_ialloc.h" | ||
39 | #include "xfs_itable.h" | 31 | #include "xfs_itable.h" |
40 | #include "xfs_btree.h" | ||
41 | #include "xfs_bmap.h" | 32 | #include "xfs_bmap.h" |
42 | #include "xfs_rtalloc.h" | 33 | #include "xfs_rtalloc.h" |
43 | #include "xfs_error.h" | 34 | #include "xfs_error.h" |
44 | #include "xfs_rw.h" | ||
45 | #include "xfs_attr.h" | 35 | #include "xfs_attr.h" |
46 | #include "xfs_buf_item.h" | 36 | #include "xfs_buf_item.h" |
47 | #include "xfs_trans_priv.h" | 37 | #include "xfs_trans_priv.h" |
@@ -59,16 +49,14 @@ xfs_trans_dqjoin( | |||
59 | xfs_trans_t *tp, | 49 | xfs_trans_t *tp, |
60 | xfs_dquot_t *dqp) | 50 | xfs_dquot_t *dqp) |
61 | { | 51 | { |
62 | xfs_dq_logitem_t *lp = &dqp->q_logitem; | ||
63 | |||
64 | ASSERT(dqp->q_transp != tp); | 52 | ASSERT(dqp->q_transp != tp); |
65 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 53 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); |
66 | ASSERT(lp->qli_dquot == dqp); | 54 | ASSERT(dqp->q_logitem.qli_dquot == dqp); |
67 | 55 | ||
68 | /* | 56 | /* |
69 | * Get a log_item_desc to point at the new item. | 57 | * Get a log_item_desc to point at the new item. |
70 | */ | 58 | */ |
71 | (void) xfs_trans_add_item(tp, (xfs_log_item_t*)(lp)); | 59 | xfs_trans_add_item(tp, &dqp->q_logitem.qli_item); |
72 | 60 | ||
73 | /* | 61 | /* |
74 | * Initialize i_transp so we can later determine if this dquot is | 62 | * Initialize i_transp so we can later determine if this dquot is |
@@ -93,16 +81,11 @@ xfs_trans_log_dquot( | |||
93 | xfs_trans_t *tp, | 81 | xfs_trans_t *tp, |
94 | xfs_dquot_t *dqp) | 82 | xfs_dquot_t *dqp) |
95 | { | 83 | { |
96 | xfs_log_item_desc_t *lidp; | ||
97 | |||
98 | ASSERT(dqp->q_transp == tp); | 84 | ASSERT(dqp->q_transp == tp); |
99 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 85 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); |
100 | 86 | ||
101 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(&dqp->q_logitem)); | ||
102 | ASSERT(lidp != NULL); | ||
103 | |||
104 | tp->t_flags |= XFS_TRANS_DIRTY; | 87 | tp->t_flags |= XFS_TRANS_DIRTY; |
105 | lidp->lid_flags |= XFS_LID_DIRTY; | 88 | dqp->q_logitem.qli_item.li_desc->lid_flags |= XFS_LID_DIRTY; |
106 | } | 89 | } |
107 | 90 | ||
108 | /* | 91 | /* |
@@ -874,9 +857,8 @@ xfs_trans_get_qoff_item( | |||
874 | /* | 857 | /* |
875 | * Get a log_item_desc to point at the new item. | 858 | * Get a log_item_desc to point at the new item. |
876 | */ | 859 | */ |
877 | (void) xfs_trans_add_item(tp, (xfs_log_item_t*)q); | 860 | xfs_trans_add_item(tp, &q->qql_item); |
878 | 861 | return q; | |
879 | return (q); | ||
880 | } | 862 | } |
881 | 863 | ||
882 | 864 | ||
@@ -890,13 +872,8 @@ xfs_trans_log_quotaoff_item( | |||
890 | xfs_trans_t *tp, | 872 | xfs_trans_t *tp, |
891 | xfs_qoff_logitem_t *qlp) | 873 | xfs_qoff_logitem_t *qlp) |
892 | { | 874 | { |
893 | xfs_log_item_desc_t *lidp; | ||
894 | |||
895 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t *)qlp); | ||
896 | ASSERT(lidp != NULL); | ||
897 | |||
898 | tp->t_flags |= XFS_TRANS_DIRTY; | 875 | tp->t_flags |= XFS_TRANS_DIRTY; |
899 | lidp->lid_flags |= XFS_LID_DIRTY; | 876 | qlp->qql_item.li_desc->lid_flags |= XFS_LID_DIRTY; |
900 | } | 877 | } |
901 | 878 | ||
902 | STATIC void | 879 | STATIC void |
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index 3f3610a7ee05..975aa10e1a47 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include "xfs_sb.h" | 22 | #include "xfs_sb.h" |
23 | #include "xfs_inum.h" | 23 | #include "xfs_inum.h" |
24 | #include "xfs_ag.h" | 24 | #include "xfs_ag.h" |
25 | #include "xfs_dmapi.h" | ||
26 | #include "xfs_mount.h" | 25 | #include "xfs_mount.h" |
27 | #include "xfs_error.h" | 26 | #include "xfs_error.h" |
28 | 27 | ||
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index a7fbe8a99b12..af168faccc7a 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -24,18 +24,13 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
37 | #include "xfs_btree.h" | 33 | #include "xfs_btree.h" |
38 | #include "xfs_ialloc.h" | ||
39 | #include "xfs_alloc.h" | 34 | #include "xfs_alloc.h" |
40 | #include "xfs_error.h" | 35 | #include "xfs_error.h" |
41 | #include "xfs_trace.h" | 36 | #include "xfs_trace.h" |
@@ -688,8 +683,6 @@ xfs_alloc_ag_vextent_near( | |||
688 | xfs_agblock_t ltbno; /* start bno of left side entry */ | 683 | xfs_agblock_t ltbno; /* start bno of left side entry */ |
689 | xfs_agblock_t ltbnoa; /* aligned ... */ | 684 | xfs_agblock_t ltbnoa; /* aligned ... */ |
690 | xfs_extlen_t ltdiff; /* difference to left side entry */ | 685 | xfs_extlen_t ltdiff; /* difference to left side entry */ |
691 | /*REFERENCED*/ | ||
692 | xfs_agblock_t ltend; /* end bno of left side entry */ | ||
693 | xfs_extlen_t ltlen; /* length of left side entry */ | 686 | xfs_extlen_t ltlen; /* length of left side entry */ |
694 | xfs_extlen_t ltlena; /* aligned ... */ | 687 | xfs_extlen_t ltlena; /* aligned ... */ |
695 | xfs_agblock_t ltnew; /* useful start bno of left side */ | 688 | xfs_agblock_t ltnew; /* useful start bno of left side */ |
@@ -814,8 +807,7 @@ xfs_alloc_ag_vextent_near( | |||
814 | if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) | 807 | if ((error = xfs_alloc_get_rec(cnt_cur, <bno, <len, &i))) |
815 | goto error0; | 808 | goto error0; |
816 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 809 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
817 | ltend = ltbno + ltlen; | 810 | ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); |
818 | ASSERT(ltend <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); | ||
819 | args->len = blen; | 811 | args->len = blen; |
820 | if (!xfs_alloc_fix_minleft(args)) { | 812 | if (!xfs_alloc_fix_minleft(args)) { |
821 | xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); | 813 | xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); |
@@ -828,7 +820,7 @@ xfs_alloc_ag_vextent_near( | |||
828 | */ | 820 | */ |
829 | args->agbno = bnew; | 821 | args->agbno = bnew; |
830 | ASSERT(bnew >= ltbno); | 822 | ASSERT(bnew >= ltbno); |
831 | ASSERT(bnew + blen <= ltend); | 823 | ASSERT(bnew + blen <= ltbno + ltlen); |
832 | /* | 824 | /* |
833 | * Set up a cursor for the by-bno tree. | 825 | * Set up a cursor for the by-bno tree. |
834 | */ | 826 | */ |
@@ -1157,7 +1149,6 @@ xfs_alloc_ag_vextent_near( | |||
1157 | /* | 1149 | /* |
1158 | * Fix up the length and compute the useful address. | 1150 | * Fix up the length and compute the useful address. |
1159 | */ | 1151 | */ |
1160 | ltend = ltbno + ltlen; | ||
1161 | args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); | 1152 | args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen); |
1162 | xfs_alloc_fix_len(args); | 1153 | xfs_alloc_fix_len(args); |
1163 | if (!xfs_alloc_fix_minleft(args)) { | 1154 | if (!xfs_alloc_fix_minleft(args)) { |
@@ -1170,7 +1161,7 @@ xfs_alloc_ag_vextent_near( | |||
1170 | (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, ltbno, | 1161 | (void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment, ltbno, |
1171 | ltlen, <new); | 1162 | ltlen, <new); |
1172 | ASSERT(ltnew >= ltbno); | 1163 | ASSERT(ltnew >= ltbno); |
1173 | ASSERT(ltnew + rlen <= ltend); | 1164 | ASSERT(ltnew + rlen <= ltbno + ltlen); |
1174 | ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); | 1165 | ASSERT(ltnew + rlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); |
1175 | args->agbno = ltnew; | 1166 | args->agbno = ltnew; |
1176 | if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen, | 1167 | if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur_lt, ltbno, ltlen, |
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 6d05199b667c..895009a97271 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h | |||
@@ -27,16 +27,16 @@ struct xfs_busy_extent; | |||
27 | /* | 27 | /* |
28 | * Freespace allocation types. Argument to xfs_alloc_[v]extent. | 28 | * Freespace allocation types. Argument to xfs_alloc_[v]extent. |
29 | */ | 29 | */ |
30 | typedef enum xfs_alloctype | 30 | #define XFS_ALLOCTYPE_ANY_AG 0x01 /* allocate anywhere, use rotor */ |
31 | { | 31 | #define XFS_ALLOCTYPE_FIRST_AG 0x02 /* ... start at ag 0 */ |
32 | XFS_ALLOCTYPE_ANY_AG, /* allocate anywhere, use rotor */ | 32 | #define XFS_ALLOCTYPE_START_AG 0x04 /* anywhere, start in this a.g. */ |
33 | XFS_ALLOCTYPE_FIRST_AG, /* ... start at ag 0 */ | 33 | #define XFS_ALLOCTYPE_THIS_AG 0x08 /* anywhere in this a.g. */ |
34 | XFS_ALLOCTYPE_START_AG, /* anywhere, start in this a.g. */ | 34 | #define XFS_ALLOCTYPE_START_BNO 0x10 /* near this block else anywhere */ |
35 | XFS_ALLOCTYPE_THIS_AG, /* anywhere in this a.g. */ | 35 | #define XFS_ALLOCTYPE_NEAR_BNO 0x20 /* in this a.g. and near this block */ |
36 | XFS_ALLOCTYPE_START_BNO, /* near this block else anywhere */ | 36 | #define XFS_ALLOCTYPE_THIS_BNO 0x40 /* at exactly this block */ |
37 | XFS_ALLOCTYPE_NEAR_BNO, /* in this a.g. and near this block */ | 37 | |
38 | XFS_ALLOCTYPE_THIS_BNO /* at exactly this block */ | 38 | /* this should become an enum again when the tracing code is fixed */ |
39 | } xfs_alloctype_t; | 39 | typedef unsigned int xfs_alloctype_t; |
40 | 40 | ||
41 | #define XFS_ALLOC_TYPES \ | 41 | #define XFS_ALLOC_TYPES \ |
42 | { XFS_ALLOCTYPE_ANY_AG, "ANY_AG" }, \ | 42 | { XFS_ALLOCTYPE_ANY_AG, "ANY_AG" }, \ |
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index 83f494218759..97f7328967fd 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c | |||
@@ -24,19 +24,14 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
37 | #include "xfs_btree.h" | 33 | #include "xfs_btree.h" |
38 | #include "xfs_btree_trace.h" | 34 | #include "xfs_btree_trace.h" |
39 | #include "xfs_ialloc.h" | ||
40 | #include "xfs_alloc.h" | 35 | #include "xfs_alloc.h" |
41 | #include "xfs_error.h" | 36 | #include "xfs_error.h" |
42 | #include "xfs_trace.h" | 37 | #include "xfs_trace.h" |
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index b9c196a53c42..c2568242a901 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -25,19 +25,13 @@ | |||
25 | #include "xfs_trans.h" | 25 | #include "xfs_trans.h" |
26 | #include "xfs_sb.h" | 26 | #include "xfs_sb.h" |
27 | #include "xfs_ag.h" | 27 | #include "xfs_ag.h" |
28 | #include "xfs_dir2.h" | ||
29 | #include "xfs_dmapi.h" | ||
30 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
31 | #include "xfs_da_btree.h" | 29 | #include "xfs_da_btree.h" |
32 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | ||
34 | #include "xfs_ialloc_btree.h" | ||
35 | #include "xfs_dir2_sf.h" | ||
36 | #include "xfs_attr_sf.h" | 31 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
38 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
39 | #include "xfs_alloc.h" | 34 | #include "xfs_alloc.h" |
40 | #include "xfs_btree.h" | ||
41 | #include "xfs_inode_item.h" | 35 | #include "xfs_inode_item.h" |
42 | #include "xfs_bmap.h" | 36 | #include "xfs_bmap.h" |
43 | #include "xfs_attr.h" | 37 | #include "xfs_attr.h" |
@@ -325,8 +319,7 @@ xfs_attr_set_int( | |||
325 | return (error); | 319 | return (error); |
326 | } | 320 | } |
327 | 321 | ||
328 | xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL); | 322 | xfs_trans_ijoin(args.trans, dp); |
329 | xfs_trans_ihold(args.trans, dp); | ||
330 | 323 | ||
331 | /* | 324 | /* |
332 | * If the attribute list is non-existent or a shortform list, | 325 | * If the attribute list is non-existent or a shortform list, |
@@ -396,10 +389,8 @@ xfs_attr_set_int( | |||
396 | * bmap_finish() may have committed the last trans and started | 389 | * bmap_finish() may have committed the last trans and started |
397 | * a new one. We need the inode to be in all transactions. | 390 | * a new one. We need the inode to be in all transactions. |
398 | */ | 391 | */ |
399 | if (committed) { | 392 | if (committed) |
400 | xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL); | 393 | xfs_trans_ijoin(args.trans, dp); |
401 | xfs_trans_ihold(args.trans, dp); | ||
402 | } | ||
403 | 394 | ||
404 | /* | 395 | /* |
405 | * Commit the leaf transformation. We'll need another (linked) | 396 | * Commit the leaf transformation. We'll need another (linked) |
@@ -544,8 +535,7 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
544 | * No need to make quota reservations here. We expect to release some | 535 | * No need to make quota reservations here. We expect to release some |
545 | * blocks not allocate in the common case. | 536 | * blocks not allocate in the common case. |
546 | */ | 537 | */ |
547 | xfs_trans_ijoin(args.trans, dp, XFS_ILOCK_EXCL); | 538 | xfs_trans_ijoin(args.trans, dp); |
548 | xfs_trans_ihold(args.trans, dp); | ||
549 | 539 | ||
550 | /* | 540 | /* |
551 | * Decide on what work routines to call based on the inode size. | 541 | * Decide on what work routines to call based on the inode size. |
@@ -821,8 +811,7 @@ xfs_attr_inactive(xfs_inode_t *dp) | |||
821 | * No need to make quota reservations here. We expect to release some | 811 | * No need to make quota reservations here. We expect to release some |
822 | * blocks, not allocate, in the common case. | 812 | * blocks, not allocate, in the common case. |
823 | */ | 813 | */ |
824 | xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL); | 814 | xfs_trans_ijoin(trans, dp); |
825 | xfs_trans_ihold(trans, dp); | ||
826 | 815 | ||
827 | /* | 816 | /* |
828 | * Decide on what work routines to call based on the inode size. | 817 | * Decide on what work routines to call based on the inode size. |
@@ -981,10 +970,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
981 | * bmap_finish() may have committed the last trans and started | 970 | * bmap_finish() may have committed the last trans and started |
982 | * a new one. We need the inode to be in all transactions. | 971 | * a new one. We need the inode to be in all transactions. |
983 | */ | 972 | */ |
984 | if (committed) { | 973 | if (committed) |
985 | xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); | 974 | xfs_trans_ijoin(args->trans, dp); |
986 | xfs_trans_ihold(args->trans, dp); | ||
987 | } | ||
988 | 975 | ||
989 | /* | 976 | /* |
990 | * Commit the current trans (including the inode) and start | 977 | * Commit the current trans (including the inode) and start |
@@ -1085,10 +1072,8 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
1085 | * and started a new one. We need the inode to be | 1072 | * and started a new one. We need the inode to be |
1086 | * in all transactions. | 1073 | * in all transactions. |
1087 | */ | 1074 | */ |
1088 | if (committed) { | 1075 | if (committed) |
1089 | xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); | 1076 | xfs_trans_ijoin(args->trans, dp); |
1090 | xfs_trans_ihold(args->trans, dp); | ||
1091 | } | ||
1092 | } else | 1077 | } else |
1093 | xfs_da_buf_done(bp); | 1078 | xfs_da_buf_done(bp); |
1094 | 1079 | ||
@@ -1161,10 +1146,8 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) | |||
1161 | * bmap_finish() may have committed the last trans and started | 1146 | * bmap_finish() may have committed the last trans and started |
1162 | * a new one. We need the inode to be in all transactions. | 1147 | * a new one. We need the inode to be in all transactions. |
1163 | */ | 1148 | */ |
1164 | if (committed) { | 1149 | if (committed) |
1165 | xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); | 1150 | xfs_trans_ijoin(args->trans, dp); |
1166 | xfs_trans_ihold(args->trans, dp); | ||
1167 | } | ||
1168 | } else | 1151 | } else |
1169 | xfs_da_buf_done(bp); | 1152 | xfs_da_buf_done(bp); |
1170 | return(0); | 1153 | return(0); |
@@ -1317,10 +1300,8 @@ restart: | |||
1317 | * and started a new one. We need the inode to be | 1300 | * and started a new one. We need the inode to be |
1318 | * in all transactions. | 1301 | * in all transactions. |
1319 | */ | 1302 | */ |
1320 | if (committed) { | 1303 | if (committed) |
1321 | xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); | 1304 | xfs_trans_ijoin(args->trans, dp); |
1322 | xfs_trans_ihold(args->trans, dp); | ||
1323 | } | ||
1324 | 1305 | ||
1325 | /* | 1306 | /* |
1326 | * Commit the node conversion and start the next | 1307 | * Commit the node conversion and start the next |
@@ -1356,10 +1337,8 @@ restart: | |||
1356 | * bmap_finish() may have committed the last trans and started | 1337 | * bmap_finish() may have committed the last trans and started |
1357 | * a new one. We need the inode to be in all transactions. | 1338 | * a new one. We need the inode to be in all transactions. |
1358 | */ | 1339 | */ |
1359 | if (committed) { | 1340 | if (committed) |
1360 | xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); | 1341 | xfs_trans_ijoin(args->trans, dp); |
1361 | xfs_trans_ihold(args->trans, dp); | ||
1362 | } | ||
1363 | } else { | 1342 | } else { |
1364 | /* | 1343 | /* |
1365 | * Addition succeeded, update Btree hashvals. | 1344 | * Addition succeeded, update Btree hashvals. |
@@ -1470,10 +1449,8 @@ restart: | |||
1470 | * and started a new one. We need the inode to be | 1449 | * and started a new one. We need the inode to be |
1471 | * in all transactions. | 1450 | * in all transactions. |
1472 | */ | 1451 | */ |
1473 | if (committed) { | 1452 | if (committed) |
1474 | xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); | 1453 | xfs_trans_ijoin(args->trans, dp); |
1475 | xfs_trans_ihold(args->trans, dp); | ||
1476 | } | ||
1477 | } | 1454 | } |
1478 | 1455 | ||
1479 | /* | 1456 | /* |
@@ -1604,10 +1581,8 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1604 | * bmap_finish() may have committed the last trans and started | 1581 | * bmap_finish() may have committed the last trans and started |
1605 | * a new one. We need the inode to be in all transactions. | 1582 | * a new one. We need the inode to be in all transactions. |
1606 | */ | 1583 | */ |
1607 | if (committed) { | 1584 | if (committed) |
1608 | xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); | 1585 | xfs_trans_ijoin(args->trans, dp); |
1609 | xfs_trans_ihold(args->trans, dp); | ||
1610 | } | ||
1611 | 1586 | ||
1612 | /* | 1587 | /* |
1613 | * Commit the Btree join operation and start a new trans. | 1588 | * Commit the Btree join operation and start a new trans. |
@@ -1658,10 +1633,8 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1658 | * and started a new one. We need the inode to be | 1633 | * and started a new one. We need the inode to be |
1659 | * in all transactions. | 1634 | * in all transactions. |
1660 | */ | 1635 | */ |
1661 | if (committed) { | 1636 | if (committed) |
1662 | xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); | 1637 | xfs_trans_ijoin(args->trans, dp); |
1663 | xfs_trans_ihold(args->trans, dp); | ||
1664 | } | ||
1665 | } else | 1638 | } else |
1666 | xfs_da_brelse(args->trans, bp); | 1639 | xfs_da_brelse(args->trans, bp); |
1667 | } | 1640 | } |
@@ -2004,7 +1977,7 @@ xfs_attr_rmtval_get(xfs_da_args_t *args) | |||
2004 | error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno, | 1977 | error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno, |
2005 | args->rmtblkcnt, | 1978 | args->rmtblkcnt, |
2006 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 1979 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, |
2007 | NULL, 0, map, &nmap, NULL, NULL); | 1980 | NULL, 0, map, &nmap, NULL); |
2008 | if (error) | 1981 | if (error) |
2009 | return(error); | 1982 | return(error); |
2010 | ASSERT(nmap >= 1); | 1983 | ASSERT(nmap >= 1); |
@@ -2083,7 +2056,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
2083 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA | | 2056 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA | |
2084 | XFS_BMAPI_WRITE, | 2057 | XFS_BMAPI_WRITE, |
2085 | args->firstblock, args->total, &map, &nmap, | 2058 | args->firstblock, args->total, &map, &nmap, |
2086 | args->flist, NULL); | 2059 | args->flist); |
2087 | if (!error) { | 2060 | if (!error) { |
2088 | error = xfs_bmap_finish(&args->trans, args->flist, | 2061 | error = xfs_bmap_finish(&args->trans, args->flist, |
2089 | &committed); | 2062 | &committed); |
@@ -2099,10 +2072,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
2099 | * bmap_finish() may have committed the last trans and started | 2072 | * bmap_finish() may have committed the last trans and started |
2100 | * a new one. We need the inode to be in all transactions. | 2073 | * a new one. We need the inode to be in all transactions. |
2101 | */ | 2074 | */ |
2102 | if (committed) { | 2075 | if (committed) |
2103 | xfs_trans_ijoin(args->trans, dp, XFS_ILOCK_EXCL); | 2076 | xfs_trans_ijoin(args->trans, dp); |
2104 | xfs_trans_ihold(args->trans, dp); | ||
2105 | } | ||
2106 | 2077 | ||
2107 | ASSERT(nmap == 1); | 2078 | ASSERT(nmap == 1); |
2108 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && | 2079 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && |
@@ -2136,7 +2107,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
2136 | args->rmtblkcnt, | 2107 | args->rmtblkcnt, |
2137 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 2108 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, |
2138 | args->firstblock, 0, &map, &nmap, | 2109 | args->firstblock, 0, &map, &nmap, |
2139 | NULL, NULL); | 2110 | NULL); |
2140 | if (error) { | 2111 | if (error) { |
2141 | return(error); | 2112 | return(error); |
2142 | } | 2113 | } |
@@ -2201,7 +2172,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) | |||
2201 | args->rmtblkcnt, | 2172 | args->rmtblkcnt, |
2202 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 2173 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, |
2203 | args->firstblock, 0, &map, &nmap, | 2174 | args->firstblock, 0, &map, &nmap, |
2204 | args->flist, NULL); | 2175 | args->flist); |
2205 | if (error) { | 2176 | if (error) { |
2206 | return(error); | 2177 | return(error); |
2207 | } | 2178 | } |
@@ -2239,7 +2210,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) | |||
2239 | error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, | 2210 | error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, |
2240 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 2211 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, |
2241 | 1, args->firstblock, args->flist, | 2212 | 1, args->firstblock, args->flist, |
2242 | NULL, &done); | 2213 | &done); |
2243 | if (!error) { | 2214 | if (!error) { |
2244 | error = xfs_bmap_finish(&args->trans, args->flist, | 2215 | error = xfs_bmap_finish(&args->trans, args->flist, |
2245 | &committed); | 2216 | &committed); |
@@ -2255,10 +2226,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) | |||
2255 | * bmap_finish() may have committed the last trans and started | 2226 | * bmap_finish() may have committed the last trans and started |
2256 | * a new one. We need the inode to be in all transactions. | 2227 | * a new one. We need the inode to be in all transactions. |
2257 | */ | 2228 | */ |
2258 | if (committed) { | 2229 | if (committed) |
2259 | xfs_trans_ijoin(args->trans, args->dp, XFS_ILOCK_EXCL); | 2230 | xfs_trans_ijoin(args->trans, args->dp); |
2260 | xfs_trans_ihold(args->trans, args->dp); | ||
2261 | } | ||
2262 | 2231 | ||
2263 | /* | 2232 | /* |
2264 | * Close out trans and start the next one in the chain. | 2233 | * Close out trans and start the next one in the chain. |
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index a90ce74fc256..a6cff8edcdb6 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
31 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
@@ -33,7 +31,6 @@ | |||
33 | #include "xfs_ialloc_btree.h" | 31 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_alloc.h" | 32 | #include "xfs_alloc.h" |
35 | #include "xfs_btree.h" | 33 | #include "xfs_btree.h" |
36 | #include "xfs_dir2_sf.h" | ||
37 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
39 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
@@ -2931,7 +2928,7 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, | |||
2931 | nmap = 1; | 2928 | nmap = 1; |
2932 | error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt, | 2929 | error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt, |
2933 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 2930 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, |
2934 | NULL, 0, &map, &nmap, NULL, NULL); | 2931 | NULL, 0, &map, &nmap, NULL); |
2935 | if (error) { | 2932 | if (error) { |
2936 | return(error); | 2933 | return(error); |
2937 | } | 2934 | } |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 99587ded043f..23f14e595c18 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -30,13 +30,10 @@ | |||
30 | #include "xfs_alloc_btree.h" | 30 | #include "xfs_alloc_btree.h" |
31 | #include "xfs_ialloc_btree.h" | 31 | #include "xfs_ialloc_btree.h" |
32 | #include "xfs_dir2_sf.h" | 32 | #include "xfs_dir2_sf.h" |
33 | #include "xfs_attr_sf.h" | ||
34 | #include "xfs_dinode.h" | 33 | #include "xfs_dinode.h" |
35 | #include "xfs_inode.h" | 34 | #include "xfs_inode.h" |
36 | #include "xfs_btree.h" | 35 | #include "xfs_btree.h" |
37 | #include "xfs_dmapi.h" | ||
38 | #include "xfs_mount.h" | 36 | #include "xfs_mount.h" |
39 | #include "xfs_ialloc.h" | ||
40 | #include "xfs_itable.h" | 37 | #include "xfs_itable.h" |
41 | #include "xfs_dir2_data.h" | 38 | #include "xfs_dir2_data.h" |
42 | #include "xfs_dir2_leaf.h" | 39 | #include "xfs_dir2_leaf.h" |
@@ -104,7 +101,6 @@ xfs_bmap_add_extent( | |||
104 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | 101 | xfs_fsblock_t *first, /* pointer to firstblock variable */ |
105 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | 102 | xfs_bmap_free_t *flist, /* list of extents to be freed */ |
106 | int *logflagsp, /* inode logging flags */ | 103 | int *logflagsp, /* inode logging flags */ |
107 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
108 | int whichfork, /* data or attr fork */ | 104 | int whichfork, /* data or attr fork */ |
109 | int rsvd); /* OK to allocate reserved blocks */ | 105 | int rsvd); /* OK to allocate reserved blocks */ |
110 | 106 | ||
@@ -122,7 +118,6 @@ xfs_bmap_add_extent_delay_real( | |||
122 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | 118 | xfs_fsblock_t *first, /* pointer to firstblock variable */ |
123 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | 119 | xfs_bmap_free_t *flist, /* list of extents to be freed */ |
124 | int *logflagsp, /* inode logging flags */ | 120 | int *logflagsp, /* inode logging flags */ |
125 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
126 | int rsvd); /* OK to allocate reserved blocks */ | 121 | int rsvd); /* OK to allocate reserved blocks */ |
127 | 122 | ||
128 | /* | 123 | /* |
@@ -135,7 +130,6 @@ xfs_bmap_add_extent_hole_delay( | |||
135 | xfs_extnum_t idx, /* extent number to update/insert */ | 130 | xfs_extnum_t idx, /* extent number to update/insert */ |
136 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 131 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
137 | int *logflagsp,/* inode logging flags */ | 132 | int *logflagsp,/* inode logging flags */ |
138 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
139 | int rsvd); /* OK to allocate reserved blocks */ | 133 | int rsvd); /* OK to allocate reserved blocks */ |
140 | 134 | ||
141 | /* | 135 | /* |
@@ -149,7 +143,6 @@ xfs_bmap_add_extent_hole_real( | |||
149 | xfs_btree_cur_t *cur, /* if null, not a btree */ | 143 | xfs_btree_cur_t *cur, /* if null, not a btree */ |
150 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 144 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
151 | int *logflagsp, /* inode logging flags */ | 145 | int *logflagsp, /* inode logging flags */ |
152 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
153 | int whichfork); /* data or attr fork */ | 146 | int whichfork); /* data or attr fork */ |
154 | 147 | ||
155 | /* | 148 | /* |
@@ -162,8 +155,7 @@ xfs_bmap_add_extent_unwritten_real( | |||
162 | xfs_extnum_t idx, /* extent number to update/insert */ | 155 | xfs_extnum_t idx, /* extent number to update/insert */ |
163 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | 156 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ |
164 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 157 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
165 | int *logflagsp, /* inode logging flags */ | 158 | int *logflagsp); /* inode logging flags */ |
166 | xfs_extdelta_t *delta); /* Change made to incore extents */ | ||
167 | 159 | ||
168 | /* | 160 | /* |
169 | * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. | 161 | * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. |
@@ -200,7 +192,6 @@ xfs_bmap_del_extent( | |||
200 | xfs_btree_cur_t *cur, /* if null, not a btree */ | 192 | xfs_btree_cur_t *cur, /* if null, not a btree */ |
201 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 193 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
202 | int *logflagsp,/* inode logging flags */ | 194 | int *logflagsp,/* inode logging flags */ |
203 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
204 | int whichfork, /* data or attr fork */ | 195 | int whichfork, /* data or attr fork */ |
205 | int rsvd); /* OK to allocate reserved blocks */ | 196 | int rsvd); /* OK to allocate reserved blocks */ |
206 | 197 | ||
@@ -489,7 +480,6 @@ xfs_bmap_add_extent( | |||
489 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | 480 | xfs_fsblock_t *first, /* pointer to firstblock variable */ |
490 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | 481 | xfs_bmap_free_t *flist, /* list of extents to be freed */ |
491 | int *logflagsp, /* inode logging flags */ | 482 | int *logflagsp, /* inode logging flags */ |
492 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
493 | int whichfork, /* data or attr fork */ | 483 | int whichfork, /* data or attr fork */ |
494 | int rsvd) /* OK to use reserved data blocks */ | 484 | int rsvd) /* OK to use reserved data blocks */ |
495 | { | 485 | { |
@@ -524,15 +514,6 @@ xfs_bmap_add_extent( | |||
524 | logflags = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); | 514 | logflags = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); |
525 | } else | 515 | } else |
526 | logflags = 0; | 516 | logflags = 0; |
527 | /* DELTA: single new extent */ | ||
528 | if (delta) { | ||
529 | if (delta->xed_startoff > new->br_startoff) | ||
530 | delta->xed_startoff = new->br_startoff; | ||
531 | if (delta->xed_blockcount < | ||
532 | new->br_startoff + new->br_blockcount) | ||
533 | delta->xed_blockcount = new->br_startoff + | ||
534 | new->br_blockcount; | ||
535 | } | ||
536 | } | 517 | } |
537 | /* | 518 | /* |
538 | * Any kind of new delayed allocation goes here. | 519 | * Any kind of new delayed allocation goes here. |
@@ -542,7 +523,7 @@ xfs_bmap_add_extent( | |||
542 | ASSERT((cur->bc_private.b.flags & | 523 | ASSERT((cur->bc_private.b.flags & |
543 | XFS_BTCUR_BPRV_WASDEL) == 0); | 524 | XFS_BTCUR_BPRV_WASDEL) == 0); |
544 | if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, new, | 525 | if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, new, |
545 | &logflags, delta, rsvd))) | 526 | &logflags, rsvd))) |
546 | goto done; | 527 | goto done; |
547 | } | 528 | } |
548 | /* | 529 | /* |
@@ -553,7 +534,7 @@ xfs_bmap_add_extent( | |||
553 | ASSERT((cur->bc_private.b.flags & | 534 | ASSERT((cur->bc_private.b.flags & |
554 | XFS_BTCUR_BPRV_WASDEL) == 0); | 535 | XFS_BTCUR_BPRV_WASDEL) == 0); |
555 | if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new, | 536 | if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new, |
556 | &logflags, delta, whichfork))) | 537 | &logflags, whichfork))) |
557 | goto done; | 538 | goto done; |
558 | } else { | 539 | } else { |
559 | xfs_bmbt_irec_t prev; /* old extent at offset idx */ | 540 | xfs_bmbt_irec_t prev; /* old extent at offset idx */ |
@@ -578,17 +559,17 @@ xfs_bmap_add_extent( | |||
578 | XFS_BTCUR_BPRV_WASDEL); | 559 | XFS_BTCUR_BPRV_WASDEL); |
579 | if ((error = xfs_bmap_add_extent_delay_real(ip, | 560 | if ((error = xfs_bmap_add_extent_delay_real(ip, |
580 | idx, &cur, new, &da_new, first, flist, | 561 | idx, &cur, new, &da_new, first, flist, |
581 | &logflags, delta, rsvd))) | 562 | &logflags, rsvd))) |
582 | goto done; | 563 | goto done; |
583 | } else if (new->br_state == XFS_EXT_NORM) { | 564 | } else if (new->br_state == XFS_EXT_NORM) { |
584 | ASSERT(new->br_state == XFS_EXT_NORM); | 565 | ASSERT(new->br_state == XFS_EXT_NORM); |
585 | if ((error = xfs_bmap_add_extent_unwritten_real( | 566 | if ((error = xfs_bmap_add_extent_unwritten_real( |
586 | ip, idx, &cur, new, &logflags, delta))) | 567 | ip, idx, &cur, new, &logflags))) |
587 | goto done; | 568 | goto done; |
588 | } else { | 569 | } else { |
589 | ASSERT(new->br_state == XFS_EXT_UNWRITTEN); | 570 | ASSERT(new->br_state == XFS_EXT_UNWRITTEN); |
590 | if ((error = xfs_bmap_add_extent_unwritten_real( | 571 | if ((error = xfs_bmap_add_extent_unwritten_real( |
591 | ip, idx, &cur, new, &logflags, delta))) | 572 | ip, idx, &cur, new, &logflags))) |
592 | goto done; | 573 | goto done; |
593 | } | 574 | } |
594 | ASSERT(*curp == cur || *curp == NULL); | 575 | ASSERT(*curp == cur || *curp == NULL); |
@@ -601,7 +582,7 @@ xfs_bmap_add_extent( | |||
601 | ASSERT((cur->bc_private.b.flags & | 582 | ASSERT((cur->bc_private.b.flags & |
602 | XFS_BTCUR_BPRV_WASDEL) == 0); | 583 | XFS_BTCUR_BPRV_WASDEL) == 0); |
603 | if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, | 584 | if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, |
604 | new, &logflags, delta, whichfork))) | 585 | new, &logflags, whichfork))) |
605 | goto done; | 586 | goto done; |
606 | } | 587 | } |
607 | } | 588 | } |
@@ -666,7 +647,6 @@ xfs_bmap_add_extent_delay_real( | |||
666 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | 647 | xfs_fsblock_t *first, /* pointer to firstblock variable */ |
667 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | 648 | xfs_bmap_free_t *flist, /* list of extents to be freed */ |
668 | int *logflagsp, /* inode logging flags */ | 649 | int *logflagsp, /* inode logging flags */ |
669 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
670 | int rsvd) /* OK to use reserved data block allocation */ | 650 | int rsvd) /* OK to use reserved data block allocation */ |
671 | { | 651 | { |
672 | xfs_btree_cur_t *cur; /* btree cursor */ | 652 | xfs_btree_cur_t *cur; /* btree cursor */ |
@@ -797,11 +777,6 @@ xfs_bmap_add_extent_delay_real( | |||
797 | goto done; | 777 | goto done; |
798 | } | 778 | } |
799 | *dnew = 0; | 779 | *dnew = 0; |
800 | /* DELTA: Three in-core extents are replaced by one. */ | ||
801 | temp = LEFT.br_startoff; | ||
802 | temp2 = LEFT.br_blockcount + | ||
803 | PREV.br_blockcount + | ||
804 | RIGHT.br_blockcount; | ||
805 | break; | 780 | break; |
806 | 781 | ||
807 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: | 782 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: |
@@ -832,10 +807,6 @@ xfs_bmap_add_extent_delay_real( | |||
832 | goto done; | 807 | goto done; |
833 | } | 808 | } |
834 | *dnew = 0; | 809 | *dnew = 0; |
835 | /* DELTA: Two in-core extents are replaced by one. */ | ||
836 | temp = LEFT.br_startoff; | ||
837 | temp2 = LEFT.br_blockcount + | ||
838 | PREV.br_blockcount; | ||
839 | break; | 810 | break; |
840 | 811 | ||
841 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: | 812 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: |
@@ -867,10 +838,6 @@ xfs_bmap_add_extent_delay_real( | |||
867 | goto done; | 838 | goto done; |
868 | } | 839 | } |
869 | *dnew = 0; | 840 | *dnew = 0; |
870 | /* DELTA: Two in-core extents are replaced by one. */ | ||
871 | temp = PREV.br_startoff; | ||
872 | temp2 = PREV.br_blockcount + | ||
873 | RIGHT.br_blockcount; | ||
874 | break; | 841 | break; |
875 | 842 | ||
876 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING: | 843 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING: |
@@ -900,9 +867,6 @@ xfs_bmap_add_extent_delay_real( | |||
900 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 867 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
901 | } | 868 | } |
902 | *dnew = 0; | 869 | *dnew = 0; |
903 | /* DELTA: The in-core extent described by new changed type. */ | ||
904 | temp = new->br_startoff; | ||
905 | temp2 = new->br_blockcount; | ||
906 | break; | 870 | break; |
907 | 871 | ||
908 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG: | 872 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG: |
@@ -942,10 +906,6 @@ xfs_bmap_add_extent_delay_real( | |||
942 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 906 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); |
943 | trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); | 907 | trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); |
944 | *dnew = temp; | 908 | *dnew = temp; |
945 | /* DELTA: The boundary between two in-core extents moved. */ | ||
946 | temp = LEFT.br_startoff; | ||
947 | temp2 = LEFT.br_blockcount + | ||
948 | PREV.br_blockcount; | ||
949 | break; | 909 | break; |
950 | 910 | ||
951 | case BMAP_LEFT_FILLING: | 911 | case BMAP_LEFT_FILLING: |
@@ -990,9 +950,6 @@ xfs_bmap_add_extent_delay_real( | |||
990 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 950 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); |
991 | trace_xfs_bmap_post_update(ip, idx + 1, state, _THIS_IP_); | 951 | trace_xfs_bmap_post_update(ip, idx + 1, state, _THIS_IP_); |
992 | *dnew = temp; | 952 | *dnew = temp; |
993 | /* DELTA: One in-core extent is split in two. */ | ||
994 | temp = PREV.br_startoff; | ||
995 | temp2 = PREV.br_blockcount; | ||
996 | break; | 953 | break; |
997 | 954 | ||
998 | case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: | 955 | case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: |
@@ -1031,10 +988,6 @@ xfs_bmap_add_extent_delay_real( | |||
1031 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 988 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); |
1032 | trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); | 989 | trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); |
1033 | *dnew = temp; | 990 | *dnew = temp; |
1034 | /* DELTA: The boundary between two in-core extents moved. */ | ||
1035 | temp = PREV.br_startoff; | ||
1036 | temp2 = PREV.br_blockcount + | ||
1037 | RIGHT.br_blockcount; | ||
1038 | break; | 991 | break; |
1039 | 992 | ||
1040 | case BMAP_RIGHT_FILLING: | 993 | case BMAP_RIGHT_FILLING: |
@@ -1078,9 +1031,6 @@ xfs_bmap_add_extent_delay_real( | |||
1078 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 1031 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); |
1079 | trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); | 1032 | trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); |
1080 | *dnew = temp; | 1033 | *dnew = temp; |
1081 | /* DELTA: One in-core extent is split in two. */ | ||
1082 | temp = PREV.br_startoff; | ||
1083 | temp2 = PREV.br_blockcount; | ||
1084 | break; | 1034 | break; |
1085 | 1035 | ||
1086 | case 0: | 1036 | case 0: |
@@ -1161,9 +1111,6 @@ xfs_bmap_add_extent_delay_real( | |||
1161 | nullstartblock((int)temp2)); | 1111 | nullstartblock((int)temp2)); |
1162 | trace_xfs_bmap_post_update(ip, idx + 2, state, _THIS_IP_); | 1112 | trace_xfs_bmap_post_update(ip, idx + 2, state, _THIS_IP_); |
1163 | *dnew = temp + temp2; | 1113 | *dnew = temp + temp2; |
1164 | /* DELTA: One in-core extent is split in three. */ | ||
1165 | temp = PREV.br_startoff; | ||
1166 | temp2 = PREV.br_blockcount; | ||
1167 | break; | 1114 | break; |
1168 | 1115 | ||
1169 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: | 1116 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: |
@@ -1179,13 +1126,6 @@ xfs_bmap_add_extent_delay_real( | |||
1179 | ASSERT(0); | 1126 | ASSERT(0); |
1180 | } | 1127 | } |
1181 | *curp = cur; | 1128 | *curp = cur; |
1182 | if (delta) { | ||
1183 | temp2 += temp; | ||
1184 | if (delta->xed_startoff > temp) | ||
1185 | delta->xed_startoff = temp; | ||
1186 | if (delta->xed_blockcount < temp2) | ||
1187 | delta->xed_blockcount = temp2; | ||
1188 | } | ||
1189 | done: | 1129 | done: |
1190 | *logflagsp = rval; | 1130 | *logflagsp = rval; |
1191 | return error; | 1131 | return error; |
@@ -1204,8 +1144,7 @@ xfs_bmap_add_extent_unwritten_real( | |||
1204 | xfs_extnum_t idx, /* extent number to update/insert */ | 1144 | xfs_extnum_t idx, /* extent number to update/insert */ |
1205 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | 1145 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ |
1206 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 1146 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
1207 | int *logflagsp, /* inode logging flags */ | 1147 | int *logflagsp) /* inode logging flags */ |
1208 | xfs_extdelta_t *delta) /* Change made to incore extents */ | ||
1209 | { | 1148 | { |
1210 | xfs_btree_cur_t *cur; /* btree cursor */ | 1149 | xfs_btree_cur_t *cur; /* btree cursor */ |
1211 | xfs_bmbt_rec_host_t *ep; /* extent entry for idx */ | 1150 | xfs_bmbt_rec_host_t *ep; /* extent entry for idx */ |
@@ -1219,8 +1158,6 @@ xfs_bmap_add_extent_unwritten_real( | |||
1219 | /* left is 0, right is 1, prev is 2 */ | 1158 | /* left is 0, right is 1, prev is 2 */ |
1220 | int rval=0; /* return value (logging flags) */ | 1159 | int rval=0; /* return value (logging flags) */ |
1221 | int state = 0;/* state bits, accessed thru macros */ | 1160 | int state = 0;/* state bits, accessed thru macros */ |
1222 | xfs_filblks_t temp=0; | ||
1223 | xfs_filblks_t temp2=0; | ||
1224 | 1161 | ||
1225 | #define LEFT r[0] | 1162 | #define LEFT r[0] |
1226 | #define RIGHT r[1] | 1163 | #define RIGHT r[1] |
@@ -1341,11 +1278,6 @@ xfs_bmap_add_extent_unwritten_real( | |||
1341 | RIGHT.br_blockcount, LEFT.br_state))) | 1278 | RIGHT.br_blockcount, LEFT.br_state))) |
1342 | goto done; | 1279 | goto done; |
1343 | } | 1280 | } |
1344 | /* DELTA: Three in-core extents are replaced by one. */ | ||
1345 | temp = LEFT.br_startoff; | ||
1346 | temp2 = LEFT.br_blockcount + | ||
1347 | PREV.br_blockcount + | ||
1348 | RIGHT.br_blockcount; | ||
1349 | break; | 1281 | break; |
1350 | 1282 | ||
1351 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: | 1283 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: |
@@ -1382,10 +1314,6 @@ xfs_bmap_add_extent_unwritten_real( | |||
1382 | LEFT.br_state))) | 1314 | LEFT.br_state))) |
1383 | goto done; | 1315 | goto done; |
1384 | } | 1316 | } |
1385 | /* DELTA: Two in-core extents are replaced by one. */ | ||
1386 | temp = LEFT.br_startoff; | ||
1387 | temp2 = LEFT.br_blockcount + | ||
1388 | PREV.br_blockcount; | ||
1389 | break; | 1317 | break; |
1390 | 1318 | ||
1391 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: | 1319 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: |
@@ -1422,10 +1350,6 @@ xfs_bmap_add_extent_unwritten_real( | |||
1422 | newext))) | 1350 | newext))) |
1423 | goto done; | 1351 | goto done; |
1424 | } | 1352 | } |
1425 | /* DELTA: Two in-core extents are replaced by one. */ | ||
1426 | temp = PREV.br_startoff; | ||
1427 | temp2 = PREV.br_blockcount + | ||
1428 | RIGHT.br_blockcount; | ||
1429 | break; | 1353 | break; |
1430 | 1354 | ||
1431 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING: | 1355 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING: |
@@ -1453,9 +1377,6 @@ xfs_bmap_add_extent_unwritten_real( | |||
1453 | newext))) | 1377 | newext))) |
1454 | goto done; | 1378 | goto done; |
1455 | } | 1379 | } |
1456 | /* DELTA: The in-core extent described by new changed type. */ | ||
1457 | temp = new->br_startoff; | ||
1458 | temp2 = new->br_blockcount; | ||
1459 | break; | 1380 | break; |
1460 | 1381 | ||
1461 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG: | 1382 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG: |
@@ -1501,10 +1422,6 @@ xfs_bmap_add_extent_unwritten_real( | |||
1501 | LEFT.br_state)) | 1422 | LEFT.br_state)) |
1502 | goto done; | 1423 | goto done; |
1503 | } | 1424 | } |
1504 | /* DELTA: The boundary between two in-core extents moved. */ | ||
1505 | temp = LEFT.br_startoff; | ||
1506 | temp2 = LEFT.br_blockcount + | ||
1507 | PREV.br_blockcount; | ||
1508 | break; | 1425 | break; |
1509 | 1426 | ||
1510 | case BMAP_LEFT_FILLING: | 1427 | case BMAP_LEFT_FILLING: |
@@ -1544,9 +1461,6 @@ xfs_bmap_add_extent_unwritten_real( | |||
1544 | goto done; | 1461 | goto done; |
1545 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1462 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1546 | } | 1463 | } |
1547 | /* DELTA: One in-core extent is split in two. */ | ||
1548 | temp = PREV.br_startoff; | ||
1549 | temp2 = PREV.br_blockcount; | ||
1550 | break; | 1464 | break; |
1551 | 1465 | ||
1552 | case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: | 1466 | case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: |
@@ -1587,10 +1501,6 @@ xfs_bmap_add_extent_unwritten_real( | |||
1587 | newext))) | 1501 | newext))) |
1588 | goto done; | 1502 | goto done; |
1589 | } | 1503 | } |
1590 | /* DELTA: The boundary between two in-core extents moved. */ | ||
1591 | temp = PREV.br_startoff; | ||
1592 | temp2 = PREV.br_blockcount + | ||
1593 | RIGHT.br_blockcount; | ||
1594 | break; | 1504 | break; |
1595 | 1505 | ||
1596 | case BMAP_RIGHT_FILLING: | 1506 | case BMAP_RIGHT_FILLING: |
@@ -1630,9 +1540,6 @@ xfs_bmap_add_extent_unwritten_real( | |||
1630 | goto done; | 1540 | goto done; |
1631 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1541 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1632 | } | 1542 | } |
1633 | /* DELTA: One in-core extent is split in two. */ | ||
1634 | temp = PREV.br_startoff; | ||
1635 | temp2 = PREV.br_blockcount; | ||
1636 | break; | 1543 | break; |
1637 | 1544 | ||
1638 | case 0: | 1545 | case 0: |
@@ -1692,9 +1599,6 @@ xfs_bmap_add_extent_unwritten_real( | |||
1692 | goto done; | 1599 | goto done; |
1693 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1600 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1694 | } | 1601 | } |
1695 | /* DELTA: One in-core extent is split in three. */ | ||
1696 | temp = PREV.br_startoff; | ||
1697 | temp2 = PREV.br_blockcount; | ||
1698 | break; | 1602 | break; |
1699 | 1603 | ||
1700 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: | 1604 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: |
@@ -1710,13 +1614,6 @@ xfs_bmap_add_extent_unwritten_real( | |||
1710 | ASSERT(0); | 1614 | ASSERT(0); |
1711 | } | 1615 | } |
1712 | *curp = cur; | 1616 | *curp = cur; |
1713 | if (delta) { | ||
1714 | temp2 += temp; | ||
1715 | if (delta->xed_startoff > temp) | ||
1716 | delta->xed_startoff = temp; | ||
1717 | if (delta->xed_blockcount < temp2) | ||
1718 | delta->xed_blockcount = temp2; | ||
1719 | } | ||
1720 | done: | 1617 | done: |
1721 | *logflagsp = rval; | 1618 | *logflagsp = rval; |
1722 | return error; | 1619 | return error; |
@@ -1736,7 +1633,6 @@ xfs_bmap_add_extent_hole_delay( | |||
1736 | xfs_extnum_t idx, /* extent number to update/insert */ | 1633 | xfs_extnum_t idx, /* extent number to update/insert */ |
1737 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 1634 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
1738 | int *logflagsp, /* inode logging flags */ | 1635 | int *logflagsp, /* inode logging flags */ |
1739 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
1740 | int rsvd) /* OK to allocate reserved blocks */ | 1636 | int rsvd) /* OK to allocate reserved blocks */ |
1741 | { | 1637 | { |
1742 | xfs_bmbt_rec_host_t *ep; /* extent record for idx */ | 1638 | xfs_bmbt_rec_host_t *ep; /* extent record for idx */ |
@@ -1747,7 +1643,6 @@ xfs_bmap_add_extent_hole_delay( | |||
1747 | xfs_bmbt_irec_t right; /* right neighbor extent entry */ | 1643 | xfs_bmbt_irec_t right; /* right neighbor extent entry */ |
1748 | int state; /* state bits, accessed thru macros */ | 1644 | int state; /* state bits, accessed thru macros */ |
1749 | xfs_filblks_t temp=0; /* temp for indirect calculations */ | 1645 | xfs_filblks_t temp=0; /* temp for indirect calculations */ |
1750 | xfs_filblks_t temp2=0; | ||
1751 | 1646 | ||
1752 | ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | 1647 | ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); |
1753 | ep = xfs_iext_get_ext(ifp, idx); | 1648 | ep = xfs_iext_get_ext(ifp, idx); |
@@ -1819,9 +1714,6 @@ xfs_bmap_add_extent_hole_delay( | |||
1819 | 1714 | ||
1820 | xfs_iext_remove(ip, idx, 1, state); | 1715 | xfs_iext_remove(ip, idx, 1, state); |
1821 | ip->i_df.if_lastex = idx - 1; | 1716 | ip->i_df.if_lastex = idx - 1; |
1822 | /* DELTA: Two in-core extents were replaced by one. */ | ||
1823 | temp2 = temp; | ||
1824 | temp = left.br_startoff; | ||
1825 | break; | 1717 | break; |
1826 | 1718 | ||
1827 | case BMAP_LEFT_CONTIG: | 1719 | case BMAP_LEFT_CONTIG: |
@@ -1841,9 +1733,6 @@ xfs_bmap_add_extent_hole_delay( | |||
1841 | trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); | 1733 | trace_xfs_bmap_post_update(ip, idx - 1, state, _THIS_IP_); |
1842 | 1734 | ||
1843 | ip->i_df.if_lastex = idx - 1; | 1735 | ip->i_df.if_lastex = idx - 1; |
1844 | /* DELTA: One in-core extent grew into a hole. */ | ||
1845 | temp2 = temp; | ||
1846 | temp = left.br_startoff; | ||
1847 | break; | 1736 | break; |
1848 | 1737 | ||
1849 | case BMAP_RIGHT_CONTIG: | 1738 | case BMAP_RIGHT_CONTIG: |
@@ -1862,9 +1751,6 @@ xfs_bmap_add_extent_hole_delay( | |||
1862 | trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); | 1751 | trace_xfs_bmap_post_update(ip, idx, state, _THIS_IP_); |
1863 | 1752 | ||
1864 | ip->i_df.if_lastex = idx; | 1753 | ip->i_df.if_lastex = idx; |
1865 | /* DELTA: One in-core extent grew into a hole. */ | ||
1866 | temp2 = temp; | ||
1867 | temp = new->br_startoff; | ||
1868 | break; | 1754 | break; |
1869 | 1755 | ||
1870 | case 0: | 1756 | case 0: |
@@ -1876,9 +1762,6 @@ xfs_bmap_add_extent_hole_delay( | |||
1876 | oldlen = newlen = 0; | 1762 | oldlen = newlen = 0; |
1877 | xfs_iext_insert(ip, idx, 1, new, state); | 1763 | xfs_iext_insert(ip, idx, 1, new, state); |
1878 | ip->i_df.if_lastex = idx; | 1764 | ip->i_df.if_lastex = idx; |
1879 | /* DELTA: A new in-core extent was added in a hole. */ | ||
1880 | temp2 = new->br_blockcount; | ||
1881 | temp = new->br_startoff; | ||
1882 | break; | 1765 | break; |
1883 | } | 1766 | } |
1884 | if (oldlen != newlen) { | 1767 | if (oldlen != newlen) { |
@@ -1889,13 +1772,6 @@ xfs_bmap_add_extent_hole_delay( | |||
1889 | * Nothing to do for disk quota accounting here. | 1772 | * Nothing to do for disk quota accounting here. |
1890 | */ | 1773 | */ |
1891 | } | 1774 | } |
1892 | if (delta) { | ||
1893 | temp2 += temp; | ||
1894 | if (delta->xed_startoff > temp) | ||
1895 | delta->xed_startoff = temp; | ||
1896 | if (delta->xed_blockcount < temp2) | ||
1897 | delta->xed_blockcount = temp2; | ||
1898 | } | ||
1899 | *logflagsp = 0; | 1775 | *logflagsp = 0; |
1900 | return 0; | 1776 | return 0; |
1901 | } | 1777 | } |
@@ -1911,7 +1787,6 @@ xfs_bmap_add_extent_hole_real( | |||
1911 | xfs_btree_cur_t *cur, /* if null, not a btree */ | 1787 | xfs_btree_cur_t *cur, /* if null, not a btree */ |
1912 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 1788 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
1913 | int *logflagsp, /* inode logging flags */ | 1789 | int *logflagsp, /* inode logging flags */ |
1914 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
1915 | int whichfork) /* data or attr fork */ | 1790 | int whichfork) /* data or attr fork */ |
1916 | { | 1791 | { |
1917 | xfs_bmbt_rec_host_t *ep; /* pointer to extent entry ins. point */ | 1792 | xfs_bmbt_rec_host_t *ep; /* pointer to extent entry ins. point */ |
@@ -1922,8 +1797,6 @@ xfs_bmap_add_extent_hole_real( | |||
1922 | xfs_bmbt_irec_t right; /* right neighbor extent entry */ | 1797 | xfs_bmbt_irec_t right; /* right neighbor extent entry */ |
1923 | int rval=0; /* return value (logging flags) */ | 1798 | int rval=0; /* return value (logging flags) */ |
1924 | int state; /* state bits, accessed thru macros */ | 1799 | int state; /* state bits, accessed thru macros */ |
1925 | xfs_filblks_t temp=0; | ||
1926 | xfs_filblks_t temp2=0; | ||
1927 | 1800 | ||
1928 | ifp = XFS_IFORK_PTR(ip, whichfork); | 1801 | ifp = XFS_IFORK_PTR(ip, whichfork); |
1929 | ASSERT(idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)); | 1802 | ASSERT(idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)); |
@@ -2020,11 +1893,6 @@ xfs_bmap_add_extent_hole_real( | |||
2020 | left.br_state))) | 1893 | left.br_state))) |
2021 | goto done; | 1894 | goto done; |
2022 | } | 1895 | } |
2023 | /* DELTA: Two in-core extents were replaced by one. */ | ||
2024 | temp = left.br_startoff; | ||
2025 | temp2 = left.br_blockcount + | ||
2026 | new->br_blockcount + | ||
2027 | right.br_blockcount; | ||
2028 | break; | 1896 | break; |
2029 | 1897 | ||
2030 | case BMAP_LEFT_CONTIG: | 1898 | case BMAP_LEFT_CONTIG: |
@@ -2056,10 +1924,6 @@ xfs_bmap_add_extent_hole_real( | |||
2056 | left.br_state))) | 1924 | left.br_state))) |
2057 | goto done; | 1925 | goto done; |
2058 | } | 1926 | } |
2059 | /* DELTA: One in-core extent grew. */ | ||
2060 | temp = left.br_startoff; | ||
2061 | temp2 = left.br_blockcount + | ||
2062 | new->br_blockcount; | ||
2063 | break; | 1927 | break; |
2064 | 1928 | ||
2065 | case BMAP_RIGHT_CONTIG: | 1929 | case BMAP_RIGHT_CONTIG: |
@@ -2092,10 +1956,6 @@ xfs_bmap_add_extent_hole_real( | |||
2092 | right.br_state))) | 1956 | right.br_state))) |
2093 | goto done; | 1957 | goto done; |
2094 | } | 1958 | } |
2095 | /* DELTA: One in-core extent grew. */ | ||
2096 | temp = new->br_startoff; | ||
2097 | temp2 = new->br_blockcount + | ||
2098 | right.br_blockcount; | ||
2099 | break; | 1959 | break; |
2100 | 1960 | ||
2101 | case 0: | 1961 | case 0: |
@@ -2123,18 +1983,8 @@ xfs_bmap_add_extent_hole_real( | |||
2123 | goto done; | 1983 | goto done; |
2124 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1984 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
2125 | } | 1985 | } |
2126 | /* DELTA: A new extent was added in a hole. */ | ||
2127 | temp = new->br_startoff; | ||
2128 | temp2 = new->br_blockcount; | ||
2129 | break; | 1986 | break; |
2130 | } | 1987 | } |
2131 | if (delta) { | ||
2132 | temp2 += temp; | ||
2133 | if (delta->xed_startoff > temp) | ||
2134 | delta->xed_startoff = temp; | ||
2135 | if (delta->xed_blockcount < temp2) | ||
2136 | delta->xed_blockcount = temp2; | ||
2137 | } | ||
2138 | done: | 1988 | done: |
2139 | *logflagsp = rval; | 1989 | *logflagsp = rval; |
2140 | return error; | 1990 | return error; |
@@ -2959,7 +2809,6 @@ xfs_bmap_del_extent( | |||
2959 | xfs_btree_cur_t *cur, /* if null, not a btree */ | 2809 | xfs_btree_cur_t *cur, /* if null, not a btree */ |
2960 | xfs_bmbt_irec_t *del, /* data to remove from extents */ | 2810 | xfs_bmbt_irec_t *del, /* data to remove from extents */ |
2961 | int *logflagsp, /* inode logging flags */ | 2811 | int *logflagsp, /* inode logging flags */ |
2962 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
2963 | int whichfork, /* data or attr fork */ | 2812 | int whichfork, /* data or attr fork */ |
2964 | int rsvd) /* OK to allocate reserved blocks */ | 2813 | int rsvd) /* OK to allocate reserved blocks */ |
2965 | { | 2814 | { |
@@ -3265,14 +3114,6 @@ xfs_bmap_del_extent( | |||
3265 | if (da_old > da_new) | 3114 | if (da_old > da_new) |
3266 | xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int64_t)(da_old - da_new), | 3115 | xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int64_t)(da_old - da_new), |
3267 | rsvd); | 3116 | rsvd); |
3268 | if (delta) { | ||
3269 | /* DELTA: report the original extent. */ | ||
3270 | if (delta->xed_startoff > got.br_startoff) | ||
3271 | delta->xed_startoff = got.br_startoff; | ||
3272 | if (delta->xed_blockcount < got.br_startoff+got.br_blockcount) | ||
3273 | delta->xed_blockcount = got.br_startoff + | ||
3274 | got.br_blockcount; | ||
3275 | } | ||
3276 | done: | 3117 | done: |
3277 | *logflagsp = flags; | 3118 | *logflagsp = flags; |
3278 | return error; | 3119 | return error; |
@@ -3754,9 +3595,10 @@ xfs_bmap_add_attrfork( | |||
3754 | ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; | 3595 | ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; |
3755 | } | 3596 | } |
3756 | ASSERT(ip->i_d.di_anextents == 0); | 3597 | ASSERT(ip->i_d.di_anextents == 0); |
3757 | IHOLD(ip); | 3598 | |
3758 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 3599 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); |
3759 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 3600 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
3601 | |||
3760 | switch (ip->i_d.di_format) { | 3602 | switch (ip->i_d.di_format) { |
3761 | case XFS_DINODE_FMT_DEV: | 3603 | case XFS_DINODE_FMT_DEV: |
3762 | ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3; | 3604 | ip->i_d.di_forkoff = roundup(sizeof(xfs_dev_t), 8) >> 3; |
@@ -4483,8 +4325,7 @@ xfs_bmapi( | |||
4483 | xfs_extlen_t total, /* total blocks needed */ | 4325 | xfs_extlen_t total, /* total blocks needed */ |
4484 | xfs_bmbt_irec_t *mval, /* output: map values */ | 4326 | xfs_bmbt_irec_t *mval, /* output: map values */ |
4485 | int *nmap, /* i/o: mval size/count */ | 4327 | int *nmap, /* i/o: mval size/count */ |
4486 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ | 4328 | xfs_bmap_free_t *flist) /* i/o: list extents to free */ |
4487 | xfs_extdelta_t *delta) /* o: change made to incore extents */ | ||
4488 | { | 4329 | { |
4489 | xfs_fsblock_t abno; /* allocated block number */ | 4330 | xfs_fsblock_t abno; /* allocated block number */ |
4490 | xfs_extlen_t alen; /* allocated extent length */ | 4331 | xfs_extlen_t alen; /* allocated extent length */ |
@@ -4596,10 +4437,7 @@ xfs_bmapi( | |||
4596 | end = bno + len; | 4437 | end = bno + len; |
4597 | obno = bno; | 4438 | obno = bno; |
4598 | bma.ip = NULL; | 4439 | bma.ip = NULL; |
4599 | if (delta) { | 4440 | |
4600 | delta->xed_startoff = NULLFILEOFF; | ||
4601 | delta->xed_blockcount = 0; | ||
4602 | } | ||
4603 | while (bno < end && n < *nmap) { | 4441 | while (bno < end && n < *nmap) { |
4604 | /* | 4442 | /* |
4605 | * Reading past eof, act as though there's a hole | 4443 | * Reading past eof, act as though there's a hole |
@@ -4620,19 +4458,13 @@ xfs_bmapi( | |||
4620 | * allocate the stuff asked for in this bmap call | 4458 | * allocate the stuff asked for in this bmap call |
4621 | * but that wouldn't be as good. | 4459 | * but that wouldn't be as good. |
4622 | */ | 4460 | */ |
4623 | if (wasdelay && !(flags & XFS_BMAPI_EXACT)) { | 4461 | if (wasdelay) { |
4624 | alen = (xfs_extlen_t)got.br_blockcount; | 4462 | alen = (xfs_extlen_t)got.br_blockcount; |
4625 | aoff = got.br_startoff; | 4463 | aoff = got.br_startoff; |
4626 | if (lastx != NULLEXTNUM && lastx) { | 4464 | if (lastx != NULLEXTNUM && lastx) { |
4627 | ep = xfs_iext_get_ext(ifp, lastx - 1); | 4465 | ep = xfs_iext_get_ext(ifp, lastx - 1); |
4628 | xfs_bmbt_get_all(ep, &prev); | 4466 | xfs_bmbt_get_all(ep, &prev); |
4629 | } | 4467 | } |
4630 | } else if (wasdelay) { | ||
4631 | alen = (xfs_extlen_t) | ||
4632 | XFS_FILBLKS_MIN(len, | ||
4633 | (got.br_startoff + | ||
4634 | got.br_blockcount) - bno); | ||
4635 | aoff = bno; | ||
4636 | } else { | 4468 | } else { |
4637 | alen = (xfs_extlen_t) | 4469 | alen = (xfs_extlen_t) |
4638 | XFS_FILBLKS_MIN(len, MAXEXTLEN); | 4470 | XFS_FILBLKS_MIN(len, MAXEXTLEN); |
@@ -4831,7 +4663,7 @@ xfs_bmapi( | |||
4831 | got.br_state = XFS_EXT_UNWRITTEN; | 4663 | got.br_state = XFS_EXT_UNWRITTEN; |
4832 | } | 4664 | } |
4833 | error = xfs_bmap_add_extent(ip, lastx, &cur, &got, | 4665 | error = xfs_bmap_add_extent(ip, lastx, &cur, &got, |
4834 | firstblock, flist, &tmp_logflags, delta, | 4666 | firstblock, flist, &tmp_logflags, |
4835 | whichfork, (flags & XFS_BMAPI_RSVBLOCKS)); | 4667 | whichfork, (flags & XFS_BMAPI_RSVBLOCKS)); |
4836 | logflags |= tmp_logflags; | 4668 | logflags |= tmp_logflags; |
4837 | if (error) | 4669 | if (error) |
@@ -4927,7 +4759,7 @@ xfs_bmapi( | |||
4927 | } | 4759 | } |
4928 | mval->br_state = XFS_EXT_NORM; | 4760 | mval->br_state = XFS_EXT_NORM; |
4929 | error = xfs_bmap_add_extent(ip, lastx, &cur, mval, | 4761 | error = xfs_bmap_add_extent(ip, lastx, &cur, mval, |
4930 | firstblock, flist, &tmp_logflags, delta, | 4762 | firstblock, flist, &tmp_logflags, |
4931 | whichfork, (flags & XFS_BMAPI_RSVBLOCKS)); | 4763 | whichfork, (flags & XFS_BMAPI_RSVBLOCKS)); |
4932 | logflags |= tmp_logflags; | 4764 | logflags |= tmp_logflags; |
4933 | if (error) | 4765 | if (error) |
@@ -5017,14 +4849,6 @@ xfs_bmapi( | |||
5017 | ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE || | 4849 | ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE || |
5018 | XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max); | 4850 | XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max); |
5019 | error = 0; | 4851 | error = 0; |
5020 | if (delta && delta->xed_startoff != NULLFILEOFF) { | ||
5021 | /* A change was actually made. | ||
5022 | * Note that delta->xed_blockount is an offset at this | ||
5023 | * point and needs to be converted to a block count. | ||
5024 | */ | ||
5025 | ASSERT(delta->xed_blockcount > delta->xed_startoff); | ||
5026 | delta->xed_blockcount -= delta->xed_startoff; | ||
5027 | } | ||
5028 | error0: | 4852 | error0: |
5029 | /* | 4853 | /* |
5030 | * Log everything. Do this after conversion, there's no point in | 4854 | * Log everything. Do this after conversion, there's no point in |
@@ -5136,8 +4960,6 @@ xfs_bunmapi( | |||
5136 | xfs_fsblock_t *firstblock, /* first allocated block | 4960 | xfs_fsblock_t *firstblock, /* first allocated block |
5137 | controls a.g. for allocs */ | 4961 | controls a.g. for allocs */ |
5138 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ | 4962 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ |
5139 | xfs_extdelta_t *delta, /* o: change made to incore | ||
5140 | extents */ | ||
5141 | int *done) /* set if not done yet */ | 4963 | int *done) /* set if not done yet */ |
5142 | { | 4964 | { |
5143 | xfs_btree_cur_t *cur; /* bmap btree cursor */ | 4965 | xfs_btree_cur_t *cur; /* bmap btree cursor */ |
@@ -5196,10 +5018,7 @@ xfs_bunmapi( | |||
5196 | bno = start + len - 1; | 5018 | bno = start + len - 1; |
5197 | ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, | 5019 | ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, |
5198 | &prev); | 5020 | &prev); |
5199 | if (delta) { | 5021 | |
5200 | delta->xed_startoff = NULLFILEOFF; | ||
5201 | delta->xed_blockcount = 0; | ||
5202 | } | ||
5203 | /* | 5022 | /* |
5204 | * Check to see if the given block number is past the end of the | 5023 | * Check to see if the given block number is past the end of the |
5205 | * file, back up to the last block if so... | 5024 | * file, back up to the last block if so... |
@@ -5297,7 +5116,7 @@ xfs_bunmapi( | |||
5297 | } | 5116 | } |
5298 | del.br_state = XFS_EXT_UNWRITTEN; | 5117 | del.br_state = XFS_EXT_UNWRITTEN; |
5299 | error = xfs_bmap_add_extent(ip, lastx, &cur, &del, | 5118 | error = xfs_bmap_add_extent(ip, lastx, &cur, &del, |
5300 | firstblock, flist, &logflags, delta, | 5119 | firstblock, flist, &logflags, |
5301 | XFS_DATA_FORK, 0); | 5120 | XFS_DATA_FORK, 0); |
5302 | if (error) | 5121 | if (error) |
5303 | goto error0; | 5122 | goto error0; |
@@ -5352,7 +5171,7 @@ xfs_bunmapi( | |||
5352 | prev.br_state = XFS_EXT_UNWRITTEN; | 5171 | prev.br_state = XFS_EXT_UNWRITTEN; |
5353 | error = xfs_bmap_add_extent(ip, lastx - 1, &cur, | 5172 | error = xfs_bmap_add_extent(ip, lastx - 1, &cur, |
5354 | &prev, firstblock, flist, &logflags, | 5173 | &prev, firstblock, flist, &logflags, |
5355 | delta, XFS_DATA_FORK, 0); | 5174 | XFS_DATA_FORK, 0); |
5356 | if (error) | 5175 | if (error) |
5357 | goto error0; | 5176 | goto error0; |
5358 | goto nodelete; | 5177 | goto nodelete; |
@@ -5361,7 +5180,7 @@ xfs_bunmapi( | |||
5361 | del.br_state = XFS_EXT_UNWRITTEN; | 5180 | del.br_state = XFS_EXT_UNWRITTEN; |
5362 | error = xfs_bmap_add_extent(ip, lastx, &cur, | 5181 | error = xfs_bmap_add_extent(ip, lastx, &cur, |
5363 | &del, firstblock, flist, &logflags, | 5182 | &del, firstblock, flist, &logflags, |
5364 | delta, XFS_DATA_FORK, 0); | 5183 | XFS_DATA_FORK, 0); |
5365 | if (error) | 5184 | if (error) |
5366 | goto error0; | 5185 | goto error0; |
5367 | goto nodelete; | 5186 | goto nodelete; |
@@ -5414,7 +5233,7 @@ xfs_bunmapi( | |||
5414 | goto error0; | 5233 | goto error0; |
5415 | } | 5234 | } |
5416 | error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del, | 5235 | error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del, |
5417 | &tmp_logflags, delta, whichfork, rsvd); | 5236 | &tmp_logflags, whichfork, rsvd); |
5418 | logflags |= tmp_logflags; | 5237 | logflags |= tmp_logflags; |
5419 | if (error) | 5238 | if (error) |
5420 | goto error0; | 5239 | goto error0; |
@@ -5471,14 +5290,6 @@ nodelete: | |||
5471 | ASSERT(ifp->if_ext_max == | 5290 | ASSERT(ifp->if_ext_max == |
5472 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); | 5291 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); |
5473 | error = 0; | 5292 | error = 0; |
5474 | if (delta && delta->xed_startoff != NULLFILEOFF) { | ||
5475 | /* A change was actually made. | ||
5476 | * Note that delta->xed_blockount is an offset at this | ||
5477 | * point and needs to be converted to a block count. | ||
5478 | */ | ||
5479 | ASSERT(delta->xed_blockcount > delta->xed_startoff); | ||
5480 | delta->xed_blockcount -= delta->xed_startoff; | ||
5481 | } | ||
5482 | error0: | 5293 | error0: |
5483 | /* | 5294 | /* |
5484 | * Log everything. Do this after conversion, there's no point in | 5295 | * Log everything. Do this after conversion, there's no point in |
@@ -5605,28 +5416,6 @@ xfs_getbmap( | |||
5605 | prealloced = 0; | 5416 | prealloced = 0; |
5606 | fixlen = 1LL << 32; | 5417 | fixlen = 1LL << 32; |
5607 | } else { | 5418 | } else { |
5608 | /* | ||
5609 | * If the BMV_IF_NO_DMAPI_READ interface bit specified, do | ||
5610 | * not generate a DMAPI read event. Otherwise, if the | ||
5611 | * DM_EVENT_READ bit is set for the file, generate a read | ||
5612 | * event in order that the DMAPI application may do its thing | ||
5613 | * before we return the extents. Usually this means restoring | ||
5614 | * user file data to regions of the file that look like holes. | ||
5615 | * | ||
5616 | * The "old behavior" (from XFS_IOC_GETBMAP) is to not specify | ||
5617 | * BMV_IF_NO_DMAPI_READ so that read events are generated. | ||
5618 | * If this were not true, callers of ioctl(XFS_IOC_GETBMAP) | ||
5619 | * could misinterpret holes in a DMAPI file as true holes, | ||
5620 | * when in fact they may represent offline user data. | ||
5621 | */ | ||
5622 | if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && | ||
5623 | !(iflags & BMV_IF_NO_DMAPI_READ)) { | ||
5624 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, | ||
5625 | 0, 0, 0, NULL); | ||
5626 | if (error) | ||
5627 | return XFS_ERROR(error); | ||
5628 | } | ||
5629 | |||
5630 | if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS && | 5419 | if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS && |
5631 | ip->i_d.di_format != XFS_DINODE_FMT_BTREE && | 5420 | ip->i_d.di_format != XFS_DINODE_FMT_BTREE && |
5632 | ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) | 5421 | ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) |
@@ -5713,7 +5502,7 @@ xfs_getbmap( | |||
5713 | error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), | 5502 | error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), |
5714 | XFS_BB_TO_FSB(mp, bmv->bmv_length), | 5503 | XFS_BB_TO_FSB(mp, bmv->bmv_length), |
5715 | bmapi_flags, NULL, 0, map, &nmap, | 5504 | bmapi_flags, NULL, 0, map, &nmap, |
5716 | NULL, NULL); | 5505 | NULL); |
5717 | if (error) | 5506 | if (error) |
5718 | goto out_free_map; | 5507 | goto out_free_map; |
5719 | ASSERT(nmap <= subnex); | 5508 | ASSERT(nmap <= subnex); |
@@ -5859,66 +5648,34 @@ xfs_bmap_eof( | |||
5859 | } | 5648 | } |
5860 | 5649 | ||
5861 | #ifdef DEBUG | 5650 | #ifdef DEBUG |
5862 | STATIC | 5651 | STATIC struct xfs_buf * |
5863 | xfs_buf_t * | ||
5864 | xfs_bmap_get_bp( | 5652 | xfs_bmap_get_bp( |
5865 | xfs_btree_cur_t *cur, | 5653 | struct xfs_btree_cur *cur, |
5866 | xfs_fsblock_t bno) | 5654 | xfs_fsblock_t bno) |
5867 | { | 5655 | { |
5868 | int i; | 5656 | struct xfs_log_item_desc *lidp; |
5869 | xfs_buf_t *bp; | 5657 | int i; |
5870 | 5658 | ||
5871 | if (!cur) | 5659 | if (!cur) |
5872 | return(NULL); | 5660 | return NULL; |
5873 | |||
5874 | bp = NULL; | ||
5875 | for(i = 0; i < XFS_BTREE_MAXLEVELS; i++) { | ||
5876 | bp = cur->bc_bufs[i]; | ||
5877 | if (!bp) break; | ||
5878 | if (XFS_BUF_ADDR(bp) == bno) | ||
5879 | break; /* Found it */ | ||
5880 | } | ||
5881 | if (i == XFS_BTREE_MAXLEVELS) | ||
5882 | bp = NULL; | ||
5883 | |||
5884 | if (!bp) { /* Chase down all the log items to see if the bp is there */ | ||
5885 | xfs_log_item_chunk_t *licp; | ||
5886 | xfs_trans_t *tp; | ||
5887 | |||
5888 | tp = cur->bc_tp; | ||
5889 | licp = &tp->t_items; | ||
5890 | while (!bp && licp != NULL) { | ||
5891 | if (xfs_lic_are_all_free(licp)) { | ||
5892 | licp = licp->lic_next; | ||
5893 | continue; | ||
5894 | } | ||
5895 | for (i = 0; i < licp->lic_unused; i++) { | ||
5896 | xfs_log_item_desc_t *lidp; | ||
5897 | xfs_log_item_t *lip; | ||
5898 | xfs_buf_log_item_t *bip; | ||
5899 | xfs_buf_t *lbp; | ||
5900 | |||
5901 | if (xfs_lic_isfree(licp, i)) { | ||
5902 | continue; | ||
5903 | } | ||
5904 | |||
5905 | lidp = xfs_lic_slot(licp, i); | ||
5906 | lip = lidp->lid_item; | ||
5907 | if (lip->li_type != XFS_LI_BUF) | ||
5908 | continue; | ||
5909 | 5661 | ||
5910 | bip = (xfs_buf_log_item_t *)lip; | 5662 | for (i = 0; i < XFS_BTREE_MAXLEVELS; i++) { |
5911 | lbp = bip->bli_buf; | 5663 | if (!cur->bc_bufs[i]) |
5664 | break; | ||
5665 | if (XFS_BUF_ADDR(cur->bc_bufs[i]) == bno) | ||
5666 | return cur->bc_bufs[i]; | ||
5667 | } | ||
5912 | 5668 | ||
5913 | if (XFS_BUF_ADDR(lbp) == bno) { | 5669 | /* Chase down all the log items to see if the bp is there */ |
5914 | bp = lbp; | 5670 | list_for_each_entry(lidp, &cur->bc_tp->t_items, lid_trans) { |
5915 | break; /* Found it */ | 5671 | struct xfs_buf_log_item *bip; |
5916 | } | 5672 | bip = (struct xfs_buf_log_item *)lidp->lid_item; |
5917 | } | 5673 | if (bip->bli_item.li_type == XFS_LI_BUF && |
5918 | licp = licp->lic_next; | 5674 | XFS_BUF_ADDR(bip->bli_buf) == bno) |
5919 | } | 5675 | return bip->bli_buf; |
5920 | } | 5676 | } |
5921 | return(bp); | 5677 | |
5678 | return NULL; | ||
5922 | } | 5679 | } |
5923 | 5680 | ||
5924 | STATIC void | 5681 | STATIC void |
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 419dafb9d87d..b13569a6179b 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -28,20 +28,6 @@ struct xfs_trans; | |||
28 | extern kmem_zone_t *xfs_bmap_free_item_zone; | 28 | extern kmem_zone_t *xfs_bmap_free_item_zone; |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * DELTA: describe a change to the in-core extent list. | ||
32 | * | ||
33 | * Internally the use of xed_blockount is somewhat funky. | ||
34 | * xed_blockcount contains an offset much of the time because this | ||
35 | * makes merging changes easier. (xfs_fileoff_t and xfs_filblks_t are | ||
36 | * the same underlying type). | ||
37 | */ | ||
38 | typedef struct xfs_extdelta | ||
39 | { | ||
40 | xfs_fileoff_t xed_startoff; /* offset of range */ | ||
41 | xfs_filblks_t xed_blockcount; /* blocks in range */ | ||
42 | } xfs_extdelta_t; | ||
43 | |||
44 | /* | ||
45 | * List of extents to be free "later". | 31 | * List of extents to be free "later". |
46 | * The list is kept sorted on xbf_startblock. | 32 | * The list is kept sorted on xbf_startblock. |
47 | */ | 33 | */ |
@@ -82,16 +68,13 @@ typedef struct xfs_bmap_free | |||
82 | #define XFS_BMAPI_DELAY 0x002 /* delayed write operation */ | 68 | #define XFS_BMAPI_DELAY 0x002 /* delayed write operation */ |
83 | #define XFS_BMAPI_ENTIRE 0x004 /* return entire extent, not trimmed */ | 69 | #define XFS_BMAPI_ENTIRE 0x004 /* return entire extent, not trimmed */ |
84 | #define XFS_BMAPI_METADATA 0x008 /* mapping metadata not user data */ | 70 | #define XFS_BMAPI_METADATA 0x008 /* mapping metadata not user data */ |
85 | #define XFS_BMAPI_EXACT 0x010 /* allocate only to spec'd bounds */ | 71 | #define XFS_BMAPI_ATTRFORK 0x010 /* use attribute fork not data */ |
86 | #define XFS_BMAPI_ATTRFORK 0x020 /* use attribute fork not data */ | 72 | #define XFS_BMAPI_RSVBLOCKS 0x020 /* OK to alloc. reserved data blocks */ |
87 | #define XFS_BMAPI_ASYNC 0x040 /* bunmapi xactions can be async */ | 73 | #define XFS_BMAPI_PREALLOC 0x040 /* preallocation op: unwritten space */ |
88 | #define XFS_BMAPI_RSVBLOCKS 0x080 /* OK to alloc. reserved data blocks */ | 74 | #define XFS_BMAPI_IGSTATE 0x080 /* Ignore state - */ |
89 | #define XFS_BMAPI_PREALLOC 0x100 /* preallocation op: unwritten space */ | ||
90 | #define XFS_BMAPI_IGSTATE 0x200 /* Ignore state - */ | ||
91 | /* combine contig. space */ | 75 | /* combine contig. space */ |
92 | #define XFS_BMAPI_CONTIG 0x400 /* must allocate only one extent */ | 76 | #define XFS_BMAPI_CONTIG 0x100 /* must allocate only one extent */ |
93 | /* XFS_BMAPI_DIRECT_IO 0x800 */ | 77 | #define XFS_BMAPI_CONVERT 0x200 /* unwritten extent conversion - */ |
94 | #define XFS_BMAPI_CONVERT 0x1000 /* unwritten extent conversion - */ | ||
95 | /* need write cache flushing and no */ | 78 | /* need write cache flushing and no */ |
96 | /* additional allocation alignments */ | 79 | /* additional allocation alignments */ |
97 | 80 | ||
@@ -100,9 +83,7 @@ typedef struct xfs_bmap_free | |||
100 | { XFS_BMAPI_DELAY, "DELAY" }, \ | 83 | { XFS_BMAPI_DELAY, "DELAY" }, \ |
101 | { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ | 84 | { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ |
102 | { XFS_BMAPI_METADATA, "METADATA" }, \ | 85 | { XFS_BMAPI_METADATA, "METADATA" }, \ |
103 | { XFS_BMAPI_EXACT, "EXACT" }, \ | ||
104 | { XFS_BMAPI_ATTRFORK, "ATTRFORK" }, \ | 86 | { XFS_BMAPI_ATTRFORK, "ATTRFORK" }, \ |
105 | { XFS_BMAPI_ASYNC, "ASYNC" }, \ | ||
106 | { XFS_BMAPI_RSVBLOCKS, "RSVBLOCKS" }, \ | 87 | { XFS_BMAPI_RSVBLOCKS, "RSVBLOCKS" }, \ |
107 | { XFS_BMAPI_PREALLOC, "PREALLOC" }, \ | 88 | { XFS_BMAPI_PREALLOC, "PREALLOC" }, \ |
108 | { XFS_BMAPI_IGSTATE, "IGSTATE" }, \ | 89 | { XFS_BMAPI_IGSTATE, "IGSTATE" }, \ |
@@ -310,9 +291,7 @@ xfs_bmapi( | |||
310 | xfs_extlen_t total, /* total blocks needed */ | 291 | xfs_extlen_t total, /* total blocks needed */ |
311 | struct xfs_bmbt_irec *mval, /* output: map values */ | 292 | struct xfs_bmbt_irec *mval, /* output: map values */ |
312 | int *nmap, /* i/o: mval size/count */ | 293 | int *nmap, /* i/o: mval size/count */ |
313 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ | 294 | xfs_bmap_free_t *flist); /* i/o: list extents to free */ |
314 | xfs_extdelta_t *delta); /* o: change made to incore | ||
315 | extents */ | ||
316 | 295 | ||
317 | /* | 296 | /* |
318 | * Map file blocks to filesystem blocks, simple version. | 297 | * Map file blocks to filesystem blocks, simple version. |
@@ -346,8 +325,6 @@ xfs_bunmapi( | |||
346 | xfs_fsblock_t *firstblock, /* first allocated block | 325 | xfs_fsblock_t *firstblock, /* first allocated block |
347 | controls a.g. for allocs */ | 326 | controls a.g. for allocs */ |
348 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ | 327 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ |
349 | xfs_extdelta_t *delta, /* o: change made to incore | ||
350 | extents */ | ||
351 | int *done); /* set if not done yet */ | 328 | int *done); /* set if not done yet */ |
352 | 329 | ||
353 | /* | 330 | /* |
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index 416e47e54b83..87d3c10b6954 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c | |||
@@ -24,21 +24,16 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
37 | #include "xfs_inode_item.h" | 33 | #include "xfs_inode_item.h" |
38 | #include "xfs_alloc.h" | 34 | #include "xfs_alloc.h" |
39 | #include "xfs_btree.h" | 35 | #include "xfs_btree.h" |
40 | #include "xfs_btree_trace.h" | 36 | #include "xfs_btree_trace.h" |
41 | #include "xfs_ialloc.h" | ||
42 | #include "xfs_itable.h" | 37 | #include "xfs_itable.h" |
43 | #include "xfs_bmap.h" | 38 | #include "xfs_bmap.h" |
44 | #include "xfs_error.h" | 39 | #include "xfs_error.h" |
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index 96be4b0f2496..829af92f0fba 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c | |||
@@ -24,20 +24,15 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
37 | #include "xfs_inode_item.h" | 33 | #include "xfs_inode_item.h" |
38 | #include "xfs_btree.h" | 34 | #include "xfs_btree.h" |
39 | #include "xfs_btree_trace.h" | 35 | #include "xfs_btree_trace.h" |
40 | #include "xfs_ialloc.h" | ||
41 | #include "xfs_error.h" | 36 | #include "xfs_error.h" |
42 | #include "xfs_trace.h" | 37 | #include "xfs_trace.h" |
43 | 38 | ||
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 02a80984aa05..1b09d7a280df 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_buf_item.h" | 28 | #include "xfs_buf_item.h" |
30 | #include "xfs_trans_priv.h" | 29 | #include "xfs_trans_priv.h" |
@@ -34,6 +33,12 @@ | |||
34 | 33 | ||
35 | kmem_zone_t *xfs_buf_item_zone; | 34 | kmem_zone_t *xfs_buf_item_zone; |
36 | 35 | ||
36 | static inline struct xfs_buf_log_item *BUF_ITEM(struct xfs_log_item *lip) | ||
37 | { | ||
38 | return container_of(lip, struct xfs_buf_log_item, bli_item); | ||
39 | } | ||
40 | |||
41 | |||
37 | #ifdef XFS_TRANS_DEBUG | 42 | #ifdef XFS_TRANS_DEBUG |
38 | /* | 43 | /* |
39 | * This function uses an alternate strategy for tracking the bytes | 44 | * This function uses an alternate strategy for tracking the bytes |
@@ -151,12 +156,13 @@ STATIC void xfs_buf_do_callbacks(xfs_buf_t *bp, xfs_log_item_t *lip); | |||
151 | */ | 156 | */ |
152 | STATIC uint | 157 | STATIC uint |
153 | xfs_buf_item_size( | 158 | xfs_buf_item_size( |
154 | xfs_buf_log_item_t *bip) | 159 | struct xfs_log_item *lip) |
155 | { | 160 | { |
156 | uint nvecs; | 161 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); |
157 | int next_bit; | 162 | struct xfs_buf *bp = bip->bli_buf; |
158 | int last_bit; | 163 | uint nvecs; |
159 | xfs_buf_t *bp; | 164 | int next_bit; |
165 | int last_bit; | ||
160 | 166 | ||
161 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 167 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
162 | if (bip->bli_flags & XFS_BLI_STALE) { | 168 | if (bip->bli_flags & XFS_BLI_STALE) { |
@@ -170,7 +176,6 @@ xfs_buf_item_size( | |||
170 | return 1; | 176 | return 1; |
171 | } | 177 | } |
172 | 178 | ||
173 | bp = bip->bli_buf; | ||
174 | ASSERT(bip->bli_flags & XFS_BLI_LOGGED); | 179 | ASSERT(bip->bli_flags & XFS_BLI_LOGGED); |
175 | nvecs = 1; | 180 | nvecs = 1; |
176 | last_bit = xfs_next_bit(bip->bli_format.blf_data_map, | 181 | last_bit = xfs_next_bit(bip->bli_format.blf_data_map, |
@@ -219,13 +224,13 @@ xfs_buf_item_size( | |||
219 | */ | 224 | */ |
220 | STATIC void | 225 | STATIC void |
221 | xfs_buf_item_format( | 226 | xfs_buf_item_format( |
222 | xfs_buf_log_item_t *bip, | 227 | struct xfs_log_item *lip, |
223 | xfs_log_iovec_t *log_vector) | 228 | struct xfs_log_iovec *vecp) |
224 | { | 229 | { |
230 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); | ||
231 | struct xfs_buf *bp = bip->bli_buf; | ||
225 | uint base_size; | 232 | uint base_size; |
226 | uint nvecs; | 233 | uint nvecs; |
227 | xfs_log_iovec_t *vecp; | ||
228 | xfs_buf_t *bp; | ||
229 | int first_bit; | 234 | int first_bit; |
230 | int last_bit; | 235 | int last_bit; |
231 | int next_bit; | 236 | int next_bit; |
@@ -235,8 +240,6 @@ xfs_buf_item_format( | |||
235 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 240 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
236 | ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || | 241 | ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || |
237 | (bip->bli_flags & XFS_BLI_STALE)); | 242 | (bip->bli_flags & XFS_BLI_STALE)); |
238 | bp = bip->bli_buf; | ||
239 | vecp = log_vector; | ||
240 | 243 | ||
241 | /* | 244 | /* |
242 | * The size of the base structure is the size of the | 245 | * The size of the base structure is the size of the |
@@ -248,7 +251,7 @@ xfs_buf_item_format( | |||
248 | base_size = | 251 | base_size = |
249 | (uint)(sizeof(xfs_buf_log_format_t) + | 252 | (uint)(sizeof(xfs_buf_log_format_t) + |
250 | ((bip->bli_format.blf_map_size - 1) * sizeof(uint))); | 253 | ((bip->bli_format.blf_map_size - 1) * sizeof(uint))); |
251 | vecp->i_addr = (xfs_caddr_t)&bip->bli_format; | 254 | vecp->i_addr = &bip->bli_format; |
252 | vecp->i_len = base_size; | 255 | vecp->i_len = base_size; |
253 | vecp->i_type = XLOG_REG_TYPE_BFORMAT; | 256 | vecp->i_type = XLOG_REG_TYPE_BFORMAT; |
254 | vecp++; | 257 | vecp++; |
@@ -263,7 +266,7 @@ xfs_buf_item_format( | |||
263 | */ | 266 | */ |
264 | if (bip->bli_flags & XFS_BLI_INODE_BUF) { | 267 | if (bip->bli_flags & XFS_BLI_INODE_BUF) { |
265 | if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && | 268 | if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && |
266 | xfs_log_item_in_current_chkpt(&bip->bli_item))) | 269 | xfs_log_item_in_current_chkpt(lip))) |
267 | bip->bli_format.blf_flags |= XFS_BLF_INODE_BUF; | 270 | bip->bli_format.blf_flags |= XFS_BLF_INODE_BUF; |
268 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; | 271 | bip->bli_flags &= ~XFS_BLI_INODE_BUF; |
269 | } | 272 | } |
@@ -356,66 +359,90 @@ xfs_buf_item_format( | |||
356 | 359 | ||
357 | /* | 360 | /* |
358 | * This is called to pin the buffer associated with the buf log item in memory | 361 | * This is called to pin the buffer associated with the buf log item in memory |
359 | * so it cannot be written out. Simply call bpin() on the buffer to do this. | 362 | * so it cannot be written out. |
360 | * | 363 | * |
361 | * We also always take a reference to the buffer log item here so that the bli | 364 | * We also always take a reference to the buffer log item here so that the bli |
362 | * is held while the item is pinned in memory. This means that we can | 365 | * is held while the item is pinned in memory. This means that we can |
363 | * unconditionally drop the reference count a transaction holds when the | 366 | * unconditionally drop the reference count a transaction holds when the |
364 | * transaction is completed. | 367 | * transaction is completed. |
365 | */ | 368 | */ |
366 | |||
367 | STATIC void | 369 | STATIC void |
368 | xfs_buf_item_pin( | 370 | xfs_buf_item_pin( |
369 | xfs_buf_log_item_t *bip) | 371 | struct xfs_log_item *lip) |
370 | { | 372 | { |
371 | xfs_buf_t *bp; | 373 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); |
372 | 374 | ||
373 | bp = bip->bli_buf; | 375 | ASSERT(XFS_BUF_ISBUSY(bip->bli_buf)); |
374 | ASSERT(XFS_BUF_ISBUSY(bp)); | ||
375 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 376 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
376 | ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || | 377 | ASSERT((bip->bli_flags & XFS_BLI_LOGGED) || |
377 | (bip->bli_flags & XFS_BLI_STALE)); | 378 | (bip->bli_flags & XFS_BLI_STALE)); |
378 | atomic_inc(&bip->bli_refcount); | 379 | |
379 | trace_xfs_buf_item_pin(bip); | 380 | trace_xfs_buf_item_pin(bip); |
380 | xfs_bpin(bp); | ||
381 | } | ||
382 | 381 | ||
382 | atomic_inc(&bip->bli_refcount); | ||
383 | atomic_inc(&bip->bli_buf->b_pin_count); | ||
384 | } | ||
383 | 385 | ||
384 | /* | 386 | /* |
385 | * This is called to unpin the buffer associated with the buf log | 387 | * This is called to unpin the buffer associated with the buf log |
386 | * item which was previously pinned with a call to xfs_buf_item_pin(). | 388 | * item which was previously pinned with a call to xfs_buf_item_pin(). |
387 | * Just call bunpin() on the buffer to do this. | ||
388 | * | 389 | * |
389 | * Also drop the reference to the buf item for the current transaction. | 390 | * Also drop the reference to the buf item for the current transaction. |
390 | * If the XFS_BLI_STALE flag is set and we are the last reference, | 391 | * If the XFS_BLI_STALE flag is set and we are the last reference, |
391 | * then free up the buf log item and unlock the buffer. | 392 | * then free up the buf log item and unlock the buffer. |
393 | * | ||
394 | * If the remove flag is set we are called from uncommit in the | ||
395 | * forced-shutdown path. If that is true and the reference count on | ||
396 | * the log item is going to drop to zero we need to free the item's | ||
397 | * descriptor in the transaction. | ||
392 | */ | 398 | */ |
393 | STATIC void | 399 | STATIC void |
394 | xfs_buf_item_unpin( | 400 | xfs_buf_item_unpin( |
395 | xfs_buf_log_item_t *bip) | 401 | struct xfs_log_item *lip, |
402 | int remove) | ||
396 | { | 403 | { |
397 | struct xfs_ail *ailp; | 404 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); |
398 | xfs_buf_t *bp; | 405 | xfs_buf_t *bp = bip->bli_buf; |
399 | int freed; | 406 | struct xfs_ail *ailp = lip->li_ailp; |
400 | int stale = bip->bli_flags & XFS_BLI_STALE; | 407 | int stale = bip->bli_flags & XFS_BLI_STALE; |
408 | int freed; | ||
401 | 409 | ||
402 | bp = bip->bli_buf; | ||
403 | ASSERT(bp != NULL); | ||
404 | ASSERT(XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *) == bip); | 410 | ASSERT(XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *) == bip); |
405 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 411 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
412 | |||
406 | trace_xfs_buf_item_unpin(bip); | 413 | trace_xfs_buf_item_unpin(bip); |
407 | 414 | ||
408 | freed = atomic_dec_and_test(&bip->bli_refcount); | 415 | freed = atomic_dec_and_test(&bip->bli_refcount); |
409 | ailp = bip->bli_item.li_ailp; | 416 | |
410 | xfs_bunpin(bp); | 417 | if (atomic_dec_and_test(&bp->b_pin_count)) |
418 | wake_up_all(&bp->b_waiters); | ||
419 | |||
411 | if (freed && stale) { | 420 | if (freed && stale) { |
412 | ASSERT(bip->bli_flags & XFS_BLI_STALE); | 421 | ASSERT(bip->bli_flags & XFS_BLI_STALE); |
413 | ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); | 422 | ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); |
414 | ASSERT(!(XFS_BUF_ISDELAYWRITE(bp))); | 423 | ASSERT(!(XFS_BUF_ISDELAYWRITE(bp))); |
415 | ASSERT(XFS_BUF_ISSTALE(bp)); | 424 | ASSERT(XFS_BUF_ISSTALE(bp)); |
416 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); | 425 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); |
426 | |||
417 | trace_xfs_buf_item_unpin_stale(bip); | 427 | trace_xfs_buf_item_unpin_stale(bip); |
418 | 428 | ||
429 | if (remove) { | ||
430 | /* | ||
431 | * We have to remove the log item from the transaction | ||
432 | * as we are about to release our reference to the | ||
433 | * buffer. If we don't, the unlock that occurs later | ||
434 | * in xfs_trans_uncommit() will ry to reference the | ||
435 | * buffer which we no longer have a hold on. | ||
436 | */ | ||
437 | xfs_trans_del_item(lip); | ||
438 | |||
439 | /* | ||
440 | * Since the transaction no longer refers to the buffer, | ||
441 | * the buffer should no longer refer to the transaction. | ||
442 | */ | ||
443 | XFS_BUF_SET_FSPRIVATE2(bp, NULL); | ||
444 | } | ||
445 | |||
419 | /* | 446 | /* |
420 | * If we get called here because of an IO error, we may | 447 | * If we get called here because of an IO error, we may |
421 | * or may not have the item on the AIL. xfs_trans_ail_delete() | 448 | * or may not have the item on the AIL. xfs_trans_ail_delete() |
@@ -437,48 +464,6 @@ xfs_buf_item_unpin( | |||
437 | } | 464 | } |
438 | 465 | ||
439 | /* | 466 | /* |
440 | * this is called from uncommit in the forced-shutdown path. | ||
441 | * we need to check to see if the reference count on the log item | ||
442 | * is going to drop to zero. If so, unpin will free the log item | ||
443 | * so we need to free the item's descriptor (that points to the item) | ||
444 | * in the transaction. | ||
445 | */ | ||
446 | STATIC void | ||
447 | xfs_buf_item_unpin_remove( | ||
448 | xfs_buf_log_item_t *bip, | ||
449 | xfs_trans_t *tp) | ||
450 | { | ||
451 | /* will xfs_buf_item_unpin() call xfs_buf_item_relse()? */ | ||
452 | if ((atomic_read(&bip->bli_refcount) == 1) && | ||
453 | (bip->bli_flags & XFS_BLI_STALE)) { | ||
454 | /* | ||
455 | * yes -- We can safely do some work here and then call | ||
456 | * buf_item_unpin to do the rest because we are | ||
457 | * are holding the buffer locked so no one else will be | ||
458 | * able to bump up the refcount. We have to remove the | ||
459 | * log item from the transaction as we are about to release | ||
460 | * our reference to the buffer. If we don't, the unlock that | ||
461 | * occurs later in the xfs_trans_uncommit() will try to | ||
462 | * reference the buffer which we no longer have a hold on. | ||
463 | */ | ||
464 | struct xfs_log_item_desc *lidp; | ||
465 | |||
466 | ASSERT(XFS_BUF_VALUSEMA(bip->bli_buf) <= 0); | ||
467 | trace_xfs_buf_item_unpin_stale(bip); | ||
468 | |||
469 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t *)bip); | ||
470 | xfs_trans_free_item(tp, lidp); | ||
471 | |||
472 | /* | ||
473 | * Since the transaction no longer refers to the buffer, the | ||
474 | * buffer should no longer refer to the transaction. | ||
475 | */ | ||
476 | XFS_BUF_SET_FSPRIVATE2(bip->bli_buf, NULL); | ||
477 | } | ||
478 | xfs_buf_item_unpin(bip); | ||
479 | } | ||
480 | |||
481 | /* | ||
482 | * This is called to attempt to lock the buffer associated with this | 467 | * This is called to attempt to lock the buffer associated with this |
483 | * buf log item. Don't sleep on the buffer lock. If we can't get | 468 | * buf log item. Don't sleep on the buffer lock. If we can't get |
484 | * the lock right away, return 0. If we can get the lock, take a | 469 | * the lock right away, return 0. If we can get the lock, take a |
@@ -488,11 +473,11 @@ xfs_buf_item_unpin_remove( | |||
488 | */ | 473 | */ |
489 | STATIC uint | 474 | STATIC uint |
490 | xfs_buf_item_trylock( | 475 | xfs_buf_item_trylock( |
491 | xfs_buf_log_item_t *bip) | 476 | struct xfs_log_item *lip) |
492 | { | 477 | { |
493 | xfs_buf_t *bp; | 478 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); |
479 | struct xfs_buf *bp = bip->bli_buf; | ||
494 | 480 | ||
495 | bp = bip->bli_buf; | ||
496 | if (XFS_BUF_ISPINNED(bp)) | 481 | if (XFS_BUF_ISPINNED(bp)) |
497 | return XFS_ITEM_PINNED; | 482 | return XFS_ITEM_PINNED; |
498 | if (!XFS_BUF_CPSEMA(bp)) | 483 | if (!XFS_BUF_CPSEMA(bp)) |
@@ -529,13 +514,12 @@ xfs_buf_item_trylock( | |||
529 | */ | 514 | */ |
530 | STATIC void | 515 | STATIC void |
531 | xfs_buf_item_unlock( | 516 | xfs_buf_item_unlock( |
532 | xfs_buf_log_item_t *bip) | 517 | struct xfs_log_item *lip) |
533 | { | 518 | { |
534 | int aborted; | 519 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); |
535 | xfs_buf_t *bp; | 520 | struct xfs_buf *bp = bip->bli_buf; |
536 | uint hold; | 521 | int aborted; |
537 | 522 | uint hold; | |
538 | bp = bip->bli_buf; | ||
539 | 523 | ||
540 | /* Clear the buffer's association with this transaction. */ | 524 | /* Clear the buffer's association with this transaction. */ |
541 | XFS_BUF_SET_FSPRIVATE2(bp, NULL); | 525 | XFS_BUF_SET_FSPRIVATE2(bp, NULL); |
@@ -546,7 +530,7 @@ xfs_buf_item_unlock( | |||
546 | * (cancelled) buffers at unpin time, but we'll never go through the | 530 | * (cancelled) buffers at unpin time, but we'll never go through the |
547 | * pin/unpin cycle if we abort inside commit. | 531 | * pin/unpin cycle if we abort inside commit. |
548 | */ | 532 | */ |
549 | aborted = (bip->bli_item.li_flags & XFS_LI_ABORTED) != 0; | 533 | aborted = (lip->li_flags & XFS_LI_ABORTED) != 0; |
550 | 534 | ||
551 | /* | 535 | /* |
552 | * Before possibly freeing the buf item, determine if we should | 536 | * Before possibly freeing the buf item, determine if we should |
@@ -607,16 +591,16 @@ xfs_buf_item_unlock( | |||
607 | */ | 591 | */ |
608 | STATIC xfs_lsn_t | 592 | STATIC xfs_lsn_t |
609 | xfs_buf_item_committed( | 593 | xfs_buf_item_committed( |
610 | xfs_buf_log_item_t *bip, | 594 | struct xfs_log_item *lip, |
611 | xfs_lsn_t lsn) | 595 | xfs_lsn_t lsn) |
612 | { | 596 | { |
597 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); | ||
598 | |||
613 | trace_xfs_buf_item_committed(bip); | 599 | trace_xfs_buf_item_committed(bip); |
614 | 600 | ||
615 | if ((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && | 601 | if ((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) && lip->li_lsn != 0) |
616 | (bip->bli_item.li_lsn != 0)) { | 602 | return lip->li_lsn; |
617 | return bip->bli_item.li_lsn; | 603 | return lsn; |
618 | } | ||
619 | return (lsn); | ||
620 | } | 604 | } |
621 | 605 | ||
622 | /* | 606 | /* |
@@ -626,15 +610,16 @@ xfs_buf_item_committed( | |||
626 | */ | 610 | */ |
627 | STATIC void | 611 | STATIC void |
628 | xfs_buf_item_push( | 612 | xfs_buf_item_push( |
629 | xfs_buf_log_item_t *bip) | 613 | struct xfs_log_item *lip) |
630 | { | 614 | { |
631 | xfs_buf_t *bp; | 615 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); |
616 | struct xfs_buf *bp = bip->bli_buf; | ||
632 | 617 | ||
633 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | 618 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); |
619 | ASSERT(!XFS_BUF_ISDELAYWRITE(bp)); | ||
620 | |||
634 | trace_xfs_buf_item_push(bip); | 621 | trace_xfs_buf_item_push(bip); |
635 | 622 | ||
636 | bp = bip->bli_buf; | ||
637 | ASSERT(!XFS_BUF_ISDELAYWRITE(bp)); | ||
638 | xfs_buf_relse(bp); | 623 | xfs_buf_relse(bp); |
639 | } | 624 | } |
640 | 625 | ||
@@ -646,22 +631,24 @@ xfs_buf_item_push( | |||
646 | */ | 631 | */ |
647 | STATIC void | 632 | STATIC void |
648 | xfs_buf_item_pushbuf( | 633 | xfs_buf_item_pushbuf( |
649 | xfs_buf_log_item_t *bip) | 634 | struct xfs_log_item *lip) |
650 | { | 635 | { |
651 | xfs_buf_t *bp; | 636 | struct xfs_buf_log_item *bip = BUF_ITEM(lip); |
637 | struct xfs_buf *bp = bip->bli_buf; | ||
652 | 638 | ||
653 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); | 639 | ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); |
640 | ASSERT(XFS_BUF_ISDELAYWRITE(bp)); | ||
641 | |||
654 | trace_xfs_buf_item_pushbuf(bip); | 642 | trace_xfs_buf_item_pushbuf(bip); |
655 | 643 | ||
656 | bp = bip->bli_buf; | ||
657 | ASSERT(XFS_BUF_ISDELAYWRITE(bp)); | ||
658 | xfs_buf_delwri_promote(bp); | 644 | xfs_buf_delwri_promote(bp); |
659 | xfs_buf_relse(bp); | 645 | xfs_buf_relse(bp); |
660 | } | 646 | } |
661 | 647 | ||
662 | /* ARGSUSED */ | ||
663 | STATIC void | 648 | STATIC void |
664 | xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn) | 649 | xfs_buf_item_committing( |
650 | struct xfs_log_item *lip, | ||
651 | xfs_lsn_t commit_lsn) | ||
665 | { | 652 | { |
666 | } | 653 | } |
667 | 654 | ||
@@ -669,21 +656,16 @@ xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn) | |||
669 | * This is the ops vector shared by all buf log items. | 656 | * This is the ops vector shared by all buf log items. |
670 | */ | 657 | */ |
671 | static struct xfs_item_ops xfs_buf_item_ops = { | 658 | static struct xfs_item_ops xfs_buf_item_ops = { |
672 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_buf_item_size, | 659 | .iop_size = xfs_buf_item_size, |
673 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 660 | .iop_format = xfs_buf_item_format, |
674 | xfs_buf_item_format, | 661 | .iop_pin = xfs_buf_item_pin, |
675 | .iop_pin = (void(*)(xfs_log_item_t*))xfs_buf_item_pin, | 662 | .iop_unpin = xfs_buf_item_unpin, |
676 | .iop_unpin = (void(*)(xfs_log_item_t*))xfs_buf_item_unpin, | 663 | .iop_trylock = xfs_buf_item_trylock, |
677 | .iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t *)) | 664 | .iop_unlock = xfs_buf_item_unlock, |
678 | xfs_buf_item_unpin_remove, | 665 | .iop_committed = xfs_buf_item_committed, |
679 | .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_buf_item_trylock, | 666 | .iop_push = xfs_buf_item_push, |
680 | .iop_unlock = (void(*)(xfs_log_item_t*))xfs_buf_item_unlock, | 667 | .iop_pushbuf = xfs_buf_item_pushbuf, |
681 | .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) | 668 | .iop_committing = xfs_buf_item_committing |
682 | xfs_buf_item_committed, | ||
683 | .iop_push = (void(*)(xfs_log_item_t*))xfs_buf_item_push, | ||
684 | .iop_pushbuf = (void(*)(xfs_log_item_t*))xfs_buf_item_pushbuf, | ||
685 | .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
686 | xfs_buf_item_committing | ||
687 | }; | 669 | }; |
688 | 670 | ||
689 | 671 | ||
@@ -712,7 +694,6 @@ xfs_buf_item_init( | |||
712 | */ | 694 | */ |
713 | if (bp->b_mount != mp) | 695 | if (bp->b_mount != mp) |
714 | bp->b_mount = mp; | 696 | bp->b_mount = mp; |
715 | XFS_BUF_SET_BDSTRAT_FUNC(bp, xfs_bdstrat_cb); | ||
716 | if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) { | 697 | if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) { |
717 | lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *); | 698 | lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *); |
718 | if (lip->li_type == XFS_LI_BUF) { | 699 | if (lip->li_type == XFS_LI_BUF) { |
@@ -1098,15 +1079,14 @@ xfs_buf_error_relse( | |||
1098 | * It is called by xfs_buf_iodone_callbacks() above which will take | 1079 | * It is called by xfs_buf_iodone_callbacks() above which will take |
1099 | * care of cleaning up the buffer itself. | 1080 | * care of cleaning up the buffer itself. |
1100 | */ | 1081 | */ |
1101 | /* ARGSUSED */ | ||
1102 | void | 1082 | void |
1103 | xfs_buf_iodone( | 1083 | xfs_buf_iodone( |
1104 | xfs_buf_t *bp, | 1084 | struct xfs_buf *bp, |
1105 | xfs_buf_log_item_t *bip) | 1085 | struct xfs_log_item *lip) |
1106 | { | 1086 | { |
1107 | struct xfs_ail *ailp = bip->bli_item.li_ailp; | 1087 | struct xfs_ail *ailp = lip->li_ailp; |
1108 | 1088 | ||
1109 | ASSERT(bip->bli_buf == bp); | 1089 | ASSERT(BUF_ITEM(lip)->bli_buf == bp); |
1110 | 1090 | ||
1111 | xfs_buf_rele(bp); | 1091 | xfs_buf_rele(bp); |
1112 | 1092 | ||
@@ -1120,6 +1100,6 @@ xfs_buf_iodone( | |||
1120 | * Either way, AIL is useless if we're forcing a shutdown. | 1100 | * Either way, AIL is useless if we're forcing a shutdown. |
1121 | */ | 1101 | */ |
1122 | spin_lock(&ailp->xa_lock); | 1102 | spin_lock(&ailp->xa_lock); |
1123 | xfs_trans_ail_delete(ailp, (xfs_log_item_t *)bip); | 1103 | xfs_trans_ail_delete(ailp, lip); |
1124 | xfs_buf_item_free(bip); | 1104 | xfs_buf_item_free(BUF_ITEM(lip)); |
1125 | } | 1105 | } |
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index f20bb472d582..0e2ed43f16c7 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h | |||
@@ -124,7 +124,7 @@ void xfs_buf_attach_iodone(struct xfs_buf *, | |||
124 | void(*)(struct xfs_buf *, xfs_log_item_t *), | 124 | void(*)(struct xfs_buf *, xfs_log_item_t *), |
125 | xfs_log_item_t *); | 125 | xfs_log_item_t *); |
126 | void xfs_buf_iodone_callbacks(struct xfs_buf *); | 126 | void xfs_buf_iodone_callbacks(struct xfs_buf *); |
127 | void xfs_buf_iodone(struct xfs_buf *, xfs_buf_log_item_t *); | 127 | void xfs_buf_iodone(struct xfs_buf *, struct xfs_log_item *); |
128 | 128 | ||
129 | #ifdef XFS_TRANS_DEBUG | 129 | #ifdef XFS_TRANS_DEBUG |
130 | void | 130 | void |
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 0ca556b4bf31..30fa0e206fba 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
@@ -25,19 +25,14 @@ | |||
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
30 | #include "xfs_da_btree.h" | 29 | #include "xfs_da_btree.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | ||
33 | #include "xfs_ialloc_btree.h" | ||
34 | #include "xfs_dir2_sf.h" | 31 | #include "xfs_dir2_sf.h" |
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
37 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
38 | #include "xfs_inode_item.h" | 34 | #include "xfs_inode_item.h" |
39 | #include "xfs_alloc.h" | 35 | #include "xfs_alloc.h" |
40 | #include "xfs_btree.h" | ||
41 | #include "xfs_bmap.h" | 36 | #include "xfs_bmap.h" |
42 | #include "xfs_attr.h" | 37 | #include "xfs_attr.h" |
43 | #include "xfs_attr_leaf.h" | 38 | #include "xfs_attr_leaf.h" |
@@ -581,16 +576,14 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, | |||
581 | xfs_da_intnode_t *node; | 576 | xfs_da_intnode_t *node; |
582 | xfs_da_node_entry_t *btree; | 577 | xfs_da_node_entry_t *btree; |
583 | int tmp; | 578 | int tmp; |
584 | xfs_mount_t *mp; | ||
585 | 579 | ||
586 | node = oldblk->bp->data; | 580 | node = oldblk->bp->data; |
587 | mp = state->mp; | ||
588 | ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); | 581 | ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); |
589 | ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count))); | 582 | ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count))); |
590 | ASSERT(newblk->blkno != 0); | 583 | ASSERT(newblk->blkno != 0); |
591 | if (state->args->whichfork == XFS_DATA_FORK) | 584 | if (state->args->whichfork == XFS_DATA_FORK) |
592 | ASSERT(newblk->blkno >= mp->m_dirleafblk && | 585 | ASSERT(newblk->blkno >= state->mp->m_dirleafblk && |
593 | newblk->blkno < mp->m_dirfreeblk); | 586 | newblk->blkno < state->mp->m_dirfreeblk); |
594 | 587 | ||
595 | /* | 588 | /* |
596 | * We may need to make some room before we insert the new node. | 589 | * We may need to make some room before we insert the new node. |
@@ -1601,7 +1594,7 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | |||
1601 | xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA| | 1594 | xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA| |
1602 | XFS_BMAPI_CONTIG, | 1595 | XFS_BMAPI_CONTIG, |
1603 | args->firstblock, args->total, &map, &nmap, | 1596 | args->firstblock, args->total, &map, &nmap, |
1604 | args->flist, NULL))) { | 1597 | args->flist))) { |
1605 | return error; | 1598 | return error; |
1606 | } | 1599 | } |
1607 | ASSERT(nmap <= 1); | 1600 | ASSERT(nmap <= 1); |
@@ -1622,8 +1615,7 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | |||
1622 | xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE| | 1615 | xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE| |
1623 | XFS_BMAPI_METADATA, | 1616 | XFS_BMAPI_METADATA, |
1624 | args->firstblock, args->total, | 1617 | args->firstblock, args->total, |
1625 | &mapp[mapi], &nmap, args->flist, | 1618 | &mapp[mapi], &nmap, args->flist))) { |
1626 | NULL))) { | ||
1627 | kmem_free(mapp); | 1619 | kmem_free(mapp); |
1628 | return error; | 1620 | return error; |
1629 | } | 1621 | } |
@@ -1884,7 +1876,7 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, | |||
1884 | */ | 1876 | */ |
1885 | if ((error = xfs_bunmapi(tp, dp, dead_blkno, count, | 1877 | if ((error = xfs_bunmapi(tp, dp, dead_blkno, count, |
1886 | xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA, | 1878 | xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA, |
1887 | 0, args->firstblock, args->flist, NULL, | 1879 | 0, args->firstblock, args->flist, |
1888 | &done)) == ENOSPC) { | 1880 | &done)) == ENOSPC) { |
1889 | if (w != XFS_DATA_FORK) | 1881 | if (w != XFS_DATA_FORK) |
1890 | break; | 1882 | break; |
@@ -1989,7 +1981,7 @@ xfs_da_do_buf( | |||
1989 | nfsb, | 1981 | nfsb, |
1990 | XFS_BMAPI_METADATA | | 1982 | XFS_BMAPI_METADATA | |
1991 | xfs_bmapi_aflag(whichfork), | 1983 | xfs_bmapi_aflag(whichfork), |
1992 | NULL, 0, mapp, &nmap, NULL, NULL))) | 1984 | NULL, 0, mapp, &nmap, NULL))) |
1993 | goto exit0; | 1985 | goto exit0; |
1994 | } | 1986 | } |
1995 | } else { | 1987 | } else { |
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 7f159d2a429a..3b9582c60a22 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
@@ -24,24 +24,15 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | ||
32 | #include "xfs_ialloc_btree.h" | ||
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 29 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
37 | #include "xfs_inode_item.h" | 31 | #include "xfs_inode_item.h" |
38 | #include "xfs_bmap.h" | 32 | #include "xfs_bmap.h" |
39 | #include "xfs_btree.h" | ||
40 | #include "xfs_ialloc.h" | ||
41 | #include "xfs_itable.h" | 33 | #include "xfs_itable.h" |
42 | #include "xfs_dfrag.h" | 34 | #include "xfs_dfrag.h" |
43 | #include "xfs_error.h" | 35 | #include "xfs_error.h" |
44 | #include "xfs_rw.h" | ||
45 | #include "xfs_vnodeops.h" | 36 | #include "xfs_vnodeops.h" |
46 | #include "xfs_trace.h" | 37 | #include "xfs_trace.h" |
47 | 38 | ||
@@ -425,11 +416,8 @@ xfs_swap_extents( | |||
425 | } | 416 | } |
426 | 417 | ||
427 | 418 | ||
428 | IHOLD(ip); | 419 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
429 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | 420 | xfs_trans_ijoin_ref(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
430 | |||
431 | IHOLD(tip); | ||
432 | xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
433 | 421 | ||
434 | xfs_trans_log_inode(tp, ip, ilf_fields); | 422 | xfs_trans_log_inode(tp, ip, ilf_fields); |
435 | xfs_trans_log_inode(tp, tip, tilf_fields); | 423 | xfs_trans_log_inode(tp, tip, tilf_fields); |
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 42520f041265..a1321bc7f192 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -25,13 +25,11 @@ | |||
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
30 | #include "xfs_da_btree.h" | 29 | #include "xfs_da_btree.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | 32 | #include "xfs_dir2_sf.h" |
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 33 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 34 | #include "xfs_inode.h" |
37 | #include "xfs_inode_item.h" | 35 | #include "xfs_inode_item.h" |
@@ -382,7 +380,7 @@ xfs_readdir( | |||
382 | int rval; /* return value */ | 380 | int rval; /* return value */ |
383 | int v; /* type-checking value */ | 381 | int v; /* type-checking value */ |
384 | 382 | ||
385 | xfs_itrace_entry(dp); | 383 | trace_xfs_readdir(dp); |
386 | 384 | ||
387 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | 385 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) |
388 | return XFS_ERROR(EIO); | 386 | return XFS_ERROR(EIO); |
@@ -549,7 +547,7 @@ xfs_dir2_grow_inode( | |||
549 | if ((error = xfs_bmapi(tp, dp, bno, count, | 547 | if ((error = xfs_bmapi(tp, dp, bno, count, |
550 | XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, | 548 | XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, |
551 | args->firstblock, args->total, &map, &nmap, | 549 | args->firstblock, args->total, &map, &nmap, |
552 | args->flist, NULL))) | 550 | args->flist))) |
553 | return error; | 551 | return error; |
554 | ASSERT(nmap <= 1); | 552 | ASSERT(nmap <= 1); |
555 | if (nmap == 1) { | 553 | if (nmap == 1) { |
@@ -581,8 +579,7 @@ xfs_dir2_grow_inode( | |||
581 | if ((error = xfs_bmapi(tp, dp, b, c, | 579 | if ((error = xfs_bmapi(tp, dp, b, c, |
582 | XFS_BMAPI_WRITE|XFS_BMAPI_METADATA, | 580 | XFS_BMAPI_WRITE|XFS_BMAPI_METADATA, |
583 | args->firstblock, args->total, | 581 | args->firstblock, args->total, |
584 | &mapp[mapi], &nmap, args->flist, | 582 | &mapp[mapi], &nmap, args->flist))) { |
585 | NULL))) { | ||
586 | kmem_free(mapp); | 583 | kmem_free(mapp); |
587 | return error; | 584 | return error; |
588 | } | 585 | } |
@@ -715,7 +712,7 @@ xfs_dir2_shrink_inode( | |||
715 | */ | 712 | */ |
716 | if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, | 713 | if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, |
717 | XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, | 714 | XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, |
718 | NULL, &done))) { | 715 | &done))) { |
719 | /* | 716 | /* |
720 | * ENOSPC actually can happen if we're in a removename with | 717 | * ENOSPC actually can happen if we're in a removename with |
721 | * no space reservation, and the resulting block removal | 718 | * no space reservation, and the resulting block removal |
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 779a267b0a84..580d99cef9e7 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
@@ -24,12 +24,10 @@ | |||
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_dir2_sf.h" | 30 | #include "xfs_dir2_sf.h" |
32 | #include "xfs_attr_sf.h" | ||
33 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
34 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
35 | #include "xfs_inode_item.h" | 33 | #include "xfs_inode_item.h" |
@@ -1073,10 +1071,10 @@ xfs_dir2_sf_to_block( | |||
1073 | */ | 1071 | */ |
1074 | 1072 | ||
1075 | buf_len = dp->i_df.if_bytes; | 1073 | buf_len = dp->i_df.if_bytes; |
1076 | buf = kmem_alloc(dp->i_df.if_bytes, KM_SLEEP); | 1074 | buf = kmem_alloc(buf_len, KM_SLEEP); |
1077 | 1075 | ||
1078 | memcpy(buf, sfp, dp->i_df.if_bytes); | 1076 | memcpy(buf, sfp, buf_len); |
1079 | xfs_idata_realloc(dp, -dp->i_df.if_bytes, XFS_DATA_FORK); | 1077 | xfs_idata_realloc(dp, -buf_len, XFS_DATA_FORK); |
1080 | dp->i_d.di_size = 0; | 1078 | dp->i_d.di_size = 0; |
1081 | xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); | 1079 | xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); |
1082 | /* | 1080 | /* |
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index 498f8d694330..921595b84f5b 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c | |||
@@ -24,12 +24,10 @@ | |||
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_dir2_sf.h" | 30 | #include "xfs_dir2_sf.h" |
32 | #include "xfs_attr_sf.h" | ||
33 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
34 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
35 | #include "xfs_dir2_data.h" | 33 | #include "xfs_dir2_data.h" |
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index e2d89854ec9e..504be8640e91 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -25,11 +25,9 @@ | |||
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
30 | #include "xfs_da_btree.h" | 29 | #include "xfs_da_btree.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_attr_sf.h" | ||
33 | #include "xfs_dir2_sf.h" | 31 | #include "xfs_dir2_sf.h" |
34 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
35 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
@@ -875,7 +873,7 @@ xfs_dir2_leaf_getdents( | |||
875 | xfs_dir2_byte_to_da(mp, | 873 | xfs_dir2_byte_to_da(mp, |
876 | XFS_DIR2_LEAF_OFFSET) - map_off, | 874 | XFS_DIR2_LEAF_OFFSET) - map_off, |
877 | XFS_BMAPI_METADATA, NULL, 0, | 875 | XFS_BMAPI_METADATA, NULL, 0, |
878 | &map[map_valid], &nmap, NULL, NULL); | 876 | &map[map_valid], &nmap, NULL); |
879 | /* | 877 | /* |
880 | * Don't know if we should ignore this or | 878 | * Don't know if we should ignore this or |
881 | * try to return an error. | 879 | * try to return an error. |
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 78fc4d9ae756..f9a0864b696a 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -24,12 +24,10 @@ | |||
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_dir2_sf.h" | 30 | #include "xfs_dir2_sf.h" |
32 | #include "xfs_attr_sf.h" | ||
33 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
34 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
35 | #include "xfs_bmap.h" | 33 | #include "xfs_bmap.h" |
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index c1a5945d463a..b1bae6b1eed9 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c | |||
@@ -24,12 +24,10 @@ | |||
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_dir2_sf.h" | 30 | #include "xfs_dir2_sf.h" |
32 | #include "xfs_attr_sf.h" | ||
33 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
34 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
35 | #include "xfs_inode_item.h" | 33 | #include "xfs_inode_item.h" |
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h deleted file mode 100644 index 2813cdd72375..000000000000 --- a/fs/xfs/xfs_dmapi.h +++ /dev/null | |||
@@ -1,170 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_DMAPI_H__ | ||
19 | #define __XFS_DMAPI_H__ | ||
20 | |||
21 | /* Values used to define the on-disk version of dm_attrname_t. All | ||
22 | * on-disk attribute names start with the 8-byte string "SGI_DMI_". | ||
23 | * | ||
24 | * In the on-disk inode, DMAPI attribute names consist of the user-provided | ||
25 | * name with the DMATTR_PREFIXSTRING pre-pended. This string must NEVER be | ||
26 | * changed. | ||
27 | */ | ||
28 | |||
29 | #define DMATTR_PREFIXLEN 8 | ||
30 | #define DMATTR_PREFIXSTRING "SGI_DMI_" | ||
31 | |||
32 | typedef enum { | ||
33 | DM_EVENT_INVALID = -1, | ||
34 | DM_EVENT_CANCEL = 0, /* not supported */ | ||
35 | DM_EVENT_MOUNT = 1, | ||
36 | DM_EVENT_PREUNMOUNT = 2, | ||
37 | DM_EVENT_UNMOUNT = 3, | ||
38 | DM_EVENT_DEBUT = 4, /* not supported */ | ||
39 | DM_EVENT_CREATE = 5, | ||
40 | DM_EVENT_CLOSE = 6, /* not supported */ | ||
41 | DM_EVENT_POSTCREATE = 7, | ||
42 | DM_EVENT_REMOVE = 8, | ||
43 | DM_EVENT_POSTREMOVE = 9, | ||
44 | DM_EVENT_RENAME = 10, | ||
45 | DM_EVENT_POSTRENAME = 11, | ||
46 | DM_EVENT_LINK = 12, | ||
47 | DM_EVENT_POSTLINK = 13, | ||
48 | DM_EVENT_SYMLINK = 14, | ||
49 | DM_EVENT_POSTSYMLINK = 15, | ||
50 | DM_EVENT_READ = 16, | ||
51 | DM_EVENT_WRITE = 17, | ||
52 | DM_EVENT_TRUNCATE = 18, | ||
53 | DM_EVENT_ATTRIBUTE = 19, | ||
54 | DM_EVENT_DESTROY = 20, | ||
55 | DM_EVENT_NOSPACE = 21, | ||
56 | DM_EVENT_USER = 22, | ||
57 | DM_EVENT_MAX = 23 | ||
58 | } dm_eventtype_t; | ||
59 | #define HAVE_DM_EVENTTYPE_T | ||
60 | |||
61 | typedef enum { | ||
62 | DM_RIGHT_NULL, | ||
63 | DM_RIGHT_SHARED, | ||
64 | DM_RIGHT_EXCL | ||
65 | } dm_right_t; | ||
66 | #define HAVE_DM_RIGHT_T | ||
67 | |||
68 | /* Defines for determining if an event message should be sent. */ | ||
69 | #ifdef HAVE_DMAPI | ||
70 | #define DM_EVENT_ENABLED(ip, event) ( \ | ||
71 | unlikely ((ip)->i_mount->m_flags & XFS_MOUNT_DMAPI) && \ | ||
72 | ( ((ip)->i_d.di_dmevmask & (1 << event)) || \ | ||
73 | ((ip)->i_mount->m_dmevmask & (1 << event)) ) \ | ||
74 | ) | ||
75 | #else | ||
76 | #define DM_EVENT_ENABLED(ip, event) (0) | ||
77 | #endif | ||
78 | |||
79 | #define DM_XFS_VALID_FS_EVENTS ( \ | ||
80 | (1 << DM_EVENT_PREUNMOUNT) | \ | ||
81 | (1 << DM_EVENT_UNMOUNT) | \ | ||
82 | (1 << DM_EVENT_NOSPACE) | \ | ||
83 | (1 << DM_EVENT_DEBUT) | \ | ||
84 | (1 << DM_EVENT_CREATE) | \ | ||
85 | (1 << DM_EVENT_POSTCREATE) | \ | ||
86 | (1 << DM_EVENT_REMOVE) | \ | ||
87 | (1 << DM_EVENT_POSTREMOVE) | \ | ||
88 | (1 << DM_EVENT_RENAME) | \ | ||
89 | (1 << DM_EVENT_POSTRENAME) | \ | ||
90 | (1 << DM_EVENT_LINK) | \ | ||
91 | (1 << DM_EVENT_POSTLINK) | \ | ||
92 | (1 << DM_EVENT_SYMLINK) | \ | ||
93 | (1 << DM_EVENT_POSTSYMLINK) | \ | ||
94 | (1 << DM_EVENT_ATTRIBUTE) | \ | ||
95 | (1 << DM_EVENT_DESTROY) ) | ||
96 | |||
97 | /* Events valid in dm_set_eventlist() when called with a file handle for | ||
98 | a regular file or a symlink. These events are persistent. | ||
99 | */ | ||
100 | |||
101 | #define DM_XFS_VALID_FILE_EVENTS ( \ | ||
102 | (1 << DM_EVENT_ATTRIBUTE) | \ | ||
103 | (1 << DM_EVENT_DESTROY) ) | ||
104 | |||
105 | /* Events valid in dm_set_eventlist() when called with a file handle for | ||
106 | a directory. These events are persistent. | ||
107 | */ | ||
108 | |||
109 | #define DM_XFS_VALID_DIRECTORY_EVENTS ( \ | ||
110 | (1 << DM_EVENT_CREATE) | \ | ||
111 | (1 << DM_EVENT_POSTCREATE) | \ | ||
112 | (1 << DM_EVENT_REMOVE) | \ | ||
113 | (1 << DM_EVENT_POSTREMOVE) | \ | ||
114 | (1 << DM_EVENT_RENAME) | \ | ||
115 | (1 << DM_EVENT_POSTRENAME) | \ | ||
116 | (1 << DM_EVENT_LINK) | \ | ||
117 | (1 << DM_EVENT_POSTLINK) | \ | ||
118 | (1 << DM_EVENT_SYMLINK) | \ | ||
119 | (1 << DM_EVENT_POSTSYMLINK) | \ | ||
120 | (1 << DM_EVENT_ATTRIBUTE) | \ | ||
121 | (1 << DM_EVENT_DESTROY) ) | ||
122 | |||
123 | /* Events supported by the XFS filesystem. */ | ||
124 | #define DM_XFS_SUPPORTED_EVENTS ( \ | ||
125 | (1 << DM_EVENT_MOUNT) | \ | ||
126 | (1 << DM_EVENT_PREUNMOUNT) | \ | ||
127 | (1 << DM_EVENT_UNMOUNT) | \ | ||
128 | (1 << DM_EVENT_NOSPACE) | \ | ||
129 | (1 << DM_EVENT_CREATE) | \ | ||
130 | (1 << DM_EVENT_POSTCREATE) | \ | ||
131 | (1 << DM_EVENT_REMOVE) | \ | ||
132 | (1 << DM_EVENT_POSTREMOVE) | \ | ||
133 | (1 << DM_EVENT_RENAME) | \ | ||
134 | (1 << DM_EVENT_POSTRENAME) | \ | ||
135 | (1 << DM_EVENT_LINK) | \ | ||
136 | (1 << DM_EVENT_POSTLINK) | \ | ||
137 | (1 << DM_EVENT_SYMLINK) | \ | ||
138 | (1 << DM_EVENT_POSTSYMLINK) | \ | ||
139 | (1 << DM_EVENT_READ) | \ | ||
140 | (1 << DM_EVENT_WRITE) | \ | ||
141 | (1 << DM_EVENT_TRUNCATE) | \ | ||
142 | (1 << DM_EVENT_ATTRIBUTE) | \ | ||
143 | (1 << DM_EVENT_DESTROY) ) | ||
144 | |||
145 | |||
146 | /* | ||
147 | * Definitions used for the flags field on dm_send_*_event(). | ||
148 | */ | ||
149 | |||
150 | #define DM_FLAGS_NDELAY 0x001 /* return EAGAIN after dm_pending() */ | ||
151 | #define DM_FLAGS_UNWANTED 0x002 /* event not in fsys dm_eventset_t */ | ||
152 | #define DM_FLAGS_IMUX 0x004 /* thread holds i_mutex */ | ||
153 | #define DM_FLAGS_IALLOCSEM_RD 0x010 /* thread holds i_alloc_sem rd */ | ||
154 | #define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */ | ||
155 | |||
156 | /* | ||
157 | * Pull in platform specific event flags defines | ||
158 | */ | ||
159 | #include "xfs_dmapi_priv.h" | ||
160 | |||
161 | /* | ||
162 | * Macros to turn caller specified delay/block flags into | ||
163 | * dm_send_xxxx_event flag DM_FLAGS_NDELAY. | ||
164 | */ | ||
165 | |||
166 | #define FILP_DELAY_FLAG(filp) ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) ? \ | ||
167 | DM_FLAGS_NDELAY : 0) | ||
168 | #define AT_DELAY_FLAG(f) ((f & XFS_ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0) | ||
169 | |||
170 | #endif /* __XFS_DMAPI_H__ */ | ||
diff --git a/fs/xfs/xfs_dmops.c b/fs/xfs/xfs_dmops.c deleted file mode 100644 index e71e2581c0c3..000000000000 --- a/fs/xfs/xfs_dmops.c +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #include "xfs.h" | ||
19 | #include "xfs_fs.h" | ||
20 | #include "xfs_types.h" | ||
21 | #include "xfs_log.h" | ||
22 | #include "xfs_trans.h" | ||
23 | #include "xfs_sb.h" | ||
24 | #include "xfs_dmapi.h" | ||
25 | #include "xfs_inum.h" | ||
26 | #include "xfs_ag.h" | ||
27 | #include "xfs_mount.h" | ||
28 | |||
29 | |||
30 | static struct xfs_dmops xfs_dmcore_stub = { | ||
31 | .xfs_send_data = (xfs_send_data_t)fs_nosys, | ||
32 | .xfs_send_mmap = (xfs_send_mmap_t)fs_noerr, | ||
33 | .xfs_send_destroy = (xfs_send_destroy_t)fs_nosys, | ||
34 | .xfs_send_namesp = (xfs_send_namesp_t)fs_nosys, | ||
35 | .xfs_send_mount = (xfs_send_mount_t)fs_nosys, | ||
36 | .xfs_send_unmount = (xfs_send_unmount_t)fs_noerr, | ||
37 | }; | ||
38 | |||
39 | int | ||
40 | xfs_dmops_get(struct xfs_mount *mp) | ||
41 | { | ||
42 | if (mp->m_flags & XFS_MOUNT_DMAPI) { | ||
43 | cmn_err(CE_WARN, | ||
44 | "XFS: dmapi support not available in this kernel."); | ||
45 | return EINVAL; | ||
46 | } | ||
47 | |||
48 | mp->m_dm_ops = &xfs_dmcore_stub; | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | void | ||
53 | xfs_dmops_put(struct xfs_mount *mp) | ||
54 | { | ||
55 | } | ||
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 047b8a8e5c29..ed9990267661 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c | |||
@@ -23,12 +23,8 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | ||
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | 26 | #include "xfs_mount.h" |
29 | #include "xfs_bmap_btree.h" | 27 | #include "xfs_bmap_btree.h" |
30 | #include "xfs_dir2_sf.h" | ||
31 | #include "xfs_attr_sf.h" | ||
32 | #include "xfs_dinode.h" | 28 | #include "xfs_dinode.h" |
33 | #include "xfs_inode.h" | 29 | #include "xfs_inode.h" |
34 | #include "xfs_utils.h" | 30 | #include "xfs_utils.h" |
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index 409fe81585fd..a55e687bf562 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "xfs_buf_item.h" | 24 | #include "xfs_buf_item.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_trans_priv.h" | 28 | #include "xfs_trans_priv.h" |
30 | #include "xfs_extfree_item.h" | 29 | #include "xfs_extfree_item.h" |
@@ -33,18 +32,19 @@ | |||
33 | kmem_zone_t *xfs_efi_zone; | 32 | kmem_zone_t *xfs_efi_zone; |
34 | kmem_zone_t *xfs_efd_zone; | 33 | kmem_zone_t *xfs_efd_zone; |
35 | 34 | ||
36 | STATIC void xfs_efi_item_unlock(xfs_efi_log_item_t *); | 35 | static inline struct xfs_efi_log_item *EFI_ITEM(struct xfs_log_item *lip) |
36 | { | ||
37 | return container_of(lip, struct xfs_efi_log_item, efi_item); | ||
38 | } | ||
37 | 39 | ||
38 | void | 40 | void |
39 | xfs_efi_item_free(xfs_efi_log_item_t *efip) | 41 | xfs_efi_item_free( |
42 | struct xfs_efi_log_item *efip) | ||
40 | { | 43 | { |
41 | int nexts = efip->efi_format.efi_nextents; | 44 | if (efip->efi_format.efi_nextents > XFS_EFI_MAX_FAST_EXTENTS) |
42 | |||
43 | if (nexts > XFS_EFI_MAX_FAST_EXTENTS) { | ||
44 | kmem_free(efip); | 45 | kmem_free(efip); |
45 | } else { | 46 | else |
46 | kmem_zone_free(xfs_efi_zone, efip); | 47 | kmem_zone_free(xfs_efi_zone, efip); |
47 | } | ||
48 | } | 48 | } |
49 | 49 | ||
50 | /* | 50 | /* |
@@ -52,9 +52,9 @@ xfs_efi_item_free(xfs_efi_log_item_t *efip) | |||
52 | * We only need 1 iovec for an efi item. It just logs the efi_log_format | 52 | * We only need 1 iovec for an efi item. It just logs the efi_log_format |
53 | * structure. | 53 | * structure. |
54 | */ | 54 | */ |
55 | /*ARGSUSED*/ | ||
56 | STATIC uint | 55 | STATIC uint |
57 | xfs_efi_item_size(xfs_efi_log_item_t *efip) | 56 | xfs_efi_item_size( |
57 | struct xfs_log_item *lip) | ||
58 | { | 58 | { |
59 | return 1; | 59 | return 1; |
60 | } | 60 | } |
@@ -67,10 +67,12 @@ xfs_efi_item_size(xfs_efi_log_item_t *efip) | |||
67 | * slots in the efi item have been filled. | 67 | * slots in the efi item have been filled. |
68 | */ | 68 | */ |
69 | STATIC void | 69 | STATIC void |
70 | xfs_efi_item_format(xfs_efi_log_item_t *efip, | 70 | xfs_efi_item_format( |
71 | xfs_log_iovec_t *log_vector) | 71 | struct xfs_log_item *lip, |
72 | struct xfs_log_iovec *log_vector) | ||
72 | { | 73 | { |
73 | uint size; | 74 | struct xfs_efi_log_item *efip = EFI_ITEM(lip); |
75 | uint size; | ||
74 | 76 | ||
75 | ASSERT(efip->efi_next_extent == efip->efi_format.efi_nextents); | 77 | ASSERT(efip->efi_next_extent == efip->efi_format.efi_nextents); |
76 | 78 | ||
@@ -80,7 +82,7 @@ xfs_efi_item_format(xfs_efi_log_item_t *efip, | |||
80 | size += (efip->efi_format.efi_nextents - 1) * sizeof(xfs_extent_t); | 82 | size += (efip->efi_format.efi_nextents - 1) * sizeof(xfs_extent_t); |
81 | efip->efi_format.efi_size = 1; | 83 | efip->efi_format.efi_size = 1; |
82 | 84 | ||
83 | log_vector->i_addr = (xfs_caddr_t)&(efip->efi_format); | 85 | log_vector->i_addr = &efip->efi_format; |
84 | log_vector->i_len = size; | 86 | log_vector->i_len = size; |
85 | log_vector->i_type = XLOG_REG_TYPE_EFI_FORMAT; | 87 | log_vector->i_type = XLOG_REG_TYPE_EFI_FORMAT; |
86 | ASSERT(size >= sizeof(xfs_efi_log_format_t)); | 88 | ASSERT(size >= sizeof(xfs_efi_log_format_t)); |
@@ -90,60 +92,33 @@ xfs_efi_item_format(xfs_efi_log_item_t *efip, | |||
90 | /* | 92 | /* |
91 | * Pinning has no meaning for an efi item, so just return. | 93 | * Pinning has no meaning for an efi item, so just return. |
92 | */ | 94 | */ |
93 | /*ARGSUSED*/ | ||
94 | STATIC void | 95 | STATIC void |
95 | xfs_efi_item_pin(xfs_efi_log_item_t *efip) | 96 | xfs_efi_item_pin( |
97 | struct xfs_log_item *lip) | ||
96 | { | 98 | { |
97 | return; | ||
98 | } | 99 | } |
99 | 100 | ||
100 | |||
101 | /* | 101 | /* |
102 | * While EFIs cannot really be pinned, the unpin operation is the | 102 | * While EFIs cannot really be pinned, the unpin operation is the |
103 | * last place at which the EFI is manipulated during a transaction. | 103 | * last place at which the EFI is manipulated during a transaction. |
104 | * Here we coordinate with xfs_efi_cancel() to determine who gets to | 104 | * Here we coordinate with xfs_efi_cancel() to determine who gets to |
105 | * free the EFI. | 105 | * free the EFI. |
106 | */ | 106 | */ |
107 | /*ARGSUSED*/ | ||
108 | STATIC void | ||
109 | xfs_efi_item_unpin(xfs_efi_log_item_t *efip) | ||
110 | { | ||
111 | struct xfs_ail *ailp = efip->efi_item.li_ailp; | ||
112 | |||
113 | spin_lock(&ailp->xa_lock); | ||
114 | if (efip->efi_flags & XFS_EFI_CANCELED) { | ||
115 | /* xfs_trans_ail_delete() drops the AIL lock. */ | ||
116 | xfs_trans_ail_delete(ailp, (xfs_log_item_t *)efip); | ||
117 | xfs_efi_item_free(efip); | ||
118 | } else { | ||
119 | efip->efi_flags |= XFS_EFI_COMMITTED; | ||
120 | spin_unlock(&ailp->xa_lock); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * like unpin only we have to also clear the xaction descriptor | ||
126 | * pointing the log item if we free the item. This routine duplicates | ||
127 | * unpin because efi_flags is protected by the AIL lock. Freeing | ||
128 | * the descriptor and then calling unpin would force us to drop the AIL | ||
129 | * lock which would open up a race condition. | ||
130 | */ | ||
131 | STATIC void | 107 | STATIC void |
132 | xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp) | 108 | xfs_efi_item_unpin( |
109 | struct xfs_log_item *lip, | ||
110 | int remove) | ||
133 | { | 111 | { |
134 | struct xfs_ail *ailp = efip->efi_item.li_ailp; | 112 | struct xfs_efi_log_item *efip = EFI_ITEM(lip); |
135 | xfs_log_item_desc_t *lidp; | 113 | struct xfs_ail *ailp = lip->li_ailp; |
136 | 114 | ||
137 | spin_lock(&ailp->xa_lock); | 115 | spin_lock(&ailp->xa_lock); |
138 | if (efip->efi_flags & XFS_EFI_CANCELED) { | 116 | if (efip->efi_flags & XFS_EFI_CANCELED) { |
139 | /* | 117 | if (remove) |
140 | * free the xaction descriptor pointing to this item | 118 | xfs_trans_del_item(lip); |
141 | */ | ||
142 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t *) efip); | ||
143 | xfs_trans_free_item(tp, lidp); | ||
144 | 119 | ||
145 | /* xfs_trans_ail_delete() drops the AIL lock. */ | 120 | /* xfs_trans_ail_delete() drops the AIL lock. */ |
146 | xfs_trans_ail_delete(ailp, (xfs_log_item_t *)efip); | 121 | xfs_trans_ail_delete(ailp, lip); |
147 | xfs_efi_item_free(efip); | 122 | xfs_efi_item_free(efip); |
148 | } else { | 123 | } else { |
149 | efip->efi_flags |= XFS_EFI_COMMITTED; | 124 | efip->efi_flags |= XFS_EFI_COMMITTED; |
@@ -158,9 +133,9 @@ xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp) | |||
158 | * XFS_ITEM_PINNED so that the caller will eventually flush the log. | 133 | * XFS_ITEM_PINNED so that the caller will eventually flush the log. |
159 | * This should help in getting the EFI out of the AIL. | 134 | * This should help in getting the EFI out of the AIL. |
160 | */ | 135 | */ |
161 | /*ARGSUSED*/ | ||
162 | STATIC uint | 136 | STATIC uint |
163 | xfs_efi_item_trylock(xfs_efi_log_item_t *efip) | 137 | xfs_efi_item_trylock( |
138 | struct xfs_log_item *lip) | ||
164 | { | 139 | { |
165 | return XFS_ITEM_PINNED; | 140 | return XFS_ITEM_PINNED; |
166 | } | 141 | } |
@@ -168,13 +143,12 @@ xfs_efi_item_trylock(xfs_efi_log_item_t *efip) | |||
168 | /* | 143 | /* |
169 | * Efi items have no locking, so just return. | 144 | * Efi items have no locking, so just return. |
170 | */ | 145 | */ |
171 | /*ARGSUSED*/ | ||
172 | STATIC void | 146 | STATIC void |
173 | xfs_efi_item_unlock(xfs_efi_log_item_t *efip) | 147 | xfs_efi_item_unlock( |
148 | struct xfs_log_item *lip) | ||
174 | { | 149 | { |
175 | if (efip->efi_item.li_flags & XFS_LI_ABORTED) | 150 | if (lip->li_flags & XFS_LI_ABORTED) |
176 | xfs_efi_item_free(efip); | 151 | xfs_efi_item_free(EFI_ITEM(lip)); |
177 | return; | ||
178 | } | 152 | } |
179 | 153 | ||
180 | /* | 154 | /* |
@@ -183,9 +157,10 @@ xfs_efi_item_unlock(xfs_efi_log_item_t *efip) | |||
183 | * flag is not paid any attention here. Checking for that is delayed | 157 | * flag is not paid any attention here. Checking for that is delayed |
184 | * until the EFI is unpinned. | 158 | * until the EFI is unpinned. |
185 | */ | 159 | */ |
186 | /*ARGSUSED*/ | ||
187 | STATIC xfs_lsn_t | 160 | STATIC xfs_lsn_t |
188 | xfs_efi_item_committed(xfs_efi_log_item_t *efip, xfs_lsn_t lsn) | 161 | xfs_efi_item_committed( |
162 | struct xfs_log_item *lip, | ||
163 | xfs_lsn_t lsn) | ||
189 | { | 164 | { |
190 | return lsn; | 165 | return lsn; |
191 | } | 166 | } |
@@ -195,11 +170,10 @@ xfs_efi_item_committed(xfs_efi_log_item_t *efip, xfs_lsn_t lsn) | |||
195 | * stuck waiting for all of its corresponding efd items to be | 170 | * stuck waiting for all of its corresponding efd items to be |
196 | * committed to disk. | 171 | * committed to disk. |
197 | */ | 172 | */ |
198 | /*ARGSUSED*/ | ||
199 | STATIC void | 173 | STATIC void |
200 | xfs_efi_item_push(xfs_efi_log_item_t *efip) | 174 | xfs_efi_item_push( |
175 | struct xfs_log_item *lip) | ||
201 | { | 176 | { |
202 | return; | ||
203 | } | 177 | } |
204 | 178 | ||
205 | /* | 179 | /* |
@@ -209,61 +183,55 @@ xfs_efi_item_push(xfs_efi_log_item_t *efip) | |||
209 | * example, for inodes, the inode is locked throughout the extent freeing | 183 | * example, for inodes, the inode is locked throughout the extent freeing |
210 | * so the dependency should be recorded there. | 184 | * so the dependency should be recorded there. |
211 | */ | 185 | */ |
212 | /*ARGSUSED*/ | ||
213 | STATIC void | 186 | STATIC void |
214 | xfs_efi_item_committing(xfs_efi_log_item_t *efip, xfs_lsn_t lsn) | 187 | xfs_efi_item_committing( |
188 | struct xfs_log_item *lip, | ||
189 | xfs_lsn_t lsn) | ||
215 | { | 190 | { |
216 | return; | ||
217 | } | 191 | } |
218 | 192 | ||
219 | /* | 193 | /* |
220 | * This is the ops vector shared by all efi log items. | 194 | * This is the ops vector shared by all efi log items. |
221 | */ | 195 | */ |
222 | static struct xfs_item_ops xfs_efi_item_ops = { | 196 | static struct xfs_item_ops xfs_efi_item_ops = { |
223 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_efi_item_size, | 197 | .iop_size = xfs_efi_item_size, |
224 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 198 | .iop_format = xfs_efi_item_format, |
225 | xfs_efi_item_format, | 199 | .iop_pin = xfs_efi_item_pin, |
226 | .iop_pin = (void(*)(xfs_log_item_t*))xfs_efi_item_pin, | 200 | .iop_unpin = xfs_efi_item_unpin, |
227 | .iop_unpin = (void(*)(xfs_log_item_t*))xfs_efi_item_unpin, | 201 | .iop_trylock = xfs_efi_item_trylock, |
228 | .iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t *)) | 202 | .iop_unlock = xfs_efi_item_unlock, |
229 | xfs_efi_item_unpin_remove, | 203 | .iop_committed = xfs_efi_item_committed, |
230 | .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_efi_item_trylock, | 204 | .iop_push = xfs_efi_item_push, |
231 | .iop_unlock = (void(*)(xfs_log_item_t*))xfs_efi_item_unlock, | 205 | .iop_committing = xfs_efi_item_committing |
232 | .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
233 | xfs_efi_item_committed, | ||
234 | .iop_push = (void(*)(xfs_log_item_t*))xfs_efi_item_push, | ||
235 | .iop_pushbuf = NULL, | ||
236 | .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
237 | xfs_efi_item_committing | ||
238 | }; | 206 | }; |
239 | 207 | ||
240 | 208 | ||
241 | /* | 209 | /* |
242 | * Allocate and initialize an efi item with the given number of extents. | 210 | * Allocate and initialize an efi item with the given number of extents. |
243 | */ | 211 | */ |
244 | xfs_efi_log_item_t * | 212 | struct xfs_efi_log_item * |
245 | xfs_efi_init(xfs_mount_t *mp, | 213 | xfs_efi_init( |
246 | uint nextents) | 214 | struct xfs_mount *mp, |
215 | uint nextents) | ||
247 | 216 | ||
248 | { | 217 | { |
249 | xfs_efi_log_item_t *efip; | 218 | struct xfs_efi_log_item *efip; |
250 | uint size; | 219 | uint size; |
251 | 220 | ||
252 | ASSERT(nextents > 0); | 221 | ASSERT(nextents > 0); |
253 | if (nextents > XFS_EFI_MAX_FAST_EXTENTS) { | 222 | if (nextents > XFS_EFI_MAX_FAST_EXTENTS) { |
254 | size = (uint)(sizeof(xfs_efi_log_item_t) + | 223 | size = (uint)(sizeof(xfs_efi_log_item_t) + |
255 | ((nextents - 1) * sizeof(xfs_extent_t))); | 224 | ((nextents - 1) * sizeof(xfs_extent_t))); |
256 | efip = (xfs_efi_log_item_t*)kmem_zalloc(size, KM_SLEEP); | 225 | efip = kmem_zalloc(size, KM_SLEEP); |
257 | } else { | 226 | } else { |
258 | efip = (xfs_efi_log_item_t*)kmem_zone_zalloc(xfs_efi_zone, | 227 | efip = kmem_zone_zalloc(xfs_efi_zone, KM_SLEEP); |
259 | KM_SLEEP); | ||
260 | } | 228 | } |
261 | 229 | ||
262 | xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops); | 230 | xfs_log_item_init(mp, &efip->efi_item, XFS_LI_EFI, &xfs_efi_item_ops); |
263 | efip->efi_format.efi_nextents = nextents; | 231 | efip->efi_format.efi_nextents = nextents; |
264 | efip->efi_format.efi_id = (__psint_t)(void*)efip; | 232 | efip->efi_format.efi_id = (__psint_t)(void*)efip; |
265 | 233 | ||
266 | return (efip); | 234 | return efip; |
267 | } | 235 | } |
268 | 236 | ||
269 | /* | 237 | /* |
@@ -276,7 +244,7 @@ xfs_efi_init(xfs_mount_t *mp, | |||
276 | int | 244 | int |
277 | xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) | 245 | xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) |
278 | { | 246 | { |
279 | xfs_efi_log_format_t *src_efi_fmt = (xfs_efi_log_format_t *)buf->i_addr; | 247 | xfs_efi_log_format_t *src_efi_fmt = buf->i_addr; |
280 | uint i; | 248 | uint i; |
281 | uint len = sizeof(xfs_efi_log_format_t) + | 249 | uint len = sizeof(xfs_efi_log_format_t) + |
282 | (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t); | 250 | (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t); |
@@ -289,8 +257,7 @@ xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) | |||
289 | memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len); | 257 | memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len); |
290 | return 0; | 258 | return 0; |
291 | } else if (buf->i_len == len32) { | 259 | } else if (buf->i_len == len32) { |
292 | xfs_efi_log_format_32_t *src_efi_fmt_32 = | 260 | xfs_efi_log_format_32_t *src_efi_fmt_32 = buf->i_addr; |
293 | (xfs_efi_log_format_32_t *)buf->i_addr; | ||
294 | 261 | ||
295 | dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; | 262 | dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; |
296 | dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; | 263 | dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; |
@@ -304,8 +271,7 @@ xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) | |||
304 | } | 271 | } |
305 | return 0; | 272 | return 0; |
306 | } else if (buf->i_len == len64) { | 273 | } else if (buf->i_len == len64) { |
307 | xfs_efi_log_format_64_t *src_efi_fmt_64 = | 274 | xfs_efi_log_format_64_t *src_efi_fmt_64 = buf->i_addr; |
308 | (xfs_efi_log_format_64_t *)buf->i_addr; | ||
309 | 275 | ||
310 | dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; | 276 | dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; |
311 | dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; | 277 | dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; |
@@ -356,16 +322,18 @@ xfs_efi_release(xfs_efi_log_item_t *efip, | |||
356 | } | 322 | } |
357 | } | 323 | } |
358 | 324 | ||
359 | STATIC void | 325 | static inline struct xfs_efd_log_item *EFD_ITEM(struct xfs_log_item *lip) |
360 | xfs_efd_item_free(xfs_efd_log_item_t *efdp) | ||
361 | { | 326 | { |
362 | int nexts = efdp->efd_format.efd_nextents; | 327 | return container_of(lip, struct xfs_efd_log_item, efd_item); |
328 | } | ||
363 | 329 | ||
364 | if (nexts > XFS_EFD_MAX_FAST_EXTENTS) { | 330 | STATIC void |
331 | xfs_efd_item_free(struct xfs_efd_log_item *efdp) | ||
332 | { | ||
333 | if (efdp->efd_format.efd_nextents > XFS_EFD_MAX_FAST_EXTENTS) | ||
365 | kmem_free(efdp); | 334 | kmem_free(efdp); |
366 | } else { | 335 | else |
367 | kmem_zone_free(xfs_efd_zone, efdp); | 336 | kmem_zone_free(xfs_efd_zone, efdp); |
368 | } | ||
369 | } | 337 | } |
370 | 338 | ||
371 | /* | 339 | /* |
@@ -373,9 +341,9 @@ xfs_efd_item_free(xfs_efd_log_item_t *efdp) | |||
373 | * We only need 1 iovec for an efd item. It just logs the efd_log_format | 341 | * We only need 1 iovec for an efd item. It just logs the efd_log_format |
374 | * structure. | 342 | * structure. |
375 | */ | 343 | */ |
376 | /*ARGSUSED*/ | ||
377 | STATIC uint | 344 | STATIC uint |
378 | xfs_efd_item_size(xfs_efd_log_item_t *efdp) | 345 | xfs_efd_item_size( |
346 | struct xfs_log_item *lip) | ||
379 | { | 347 | { |
380 | return 1; | 348 | return 1; |
381 | } | 349 | } |
@@ -388,10 +356,12 @@ xfs_efd_item_size(xfs_efd_log_item_t *efdp) | |||
388 | * slots in the efd item have been filled. | 356 | * slots in the efd item have been filled. |
389 | */ | 357 | */ |
390 | STATIC void | 358 | STATIC void |
391 | xfs_efd_item_format(xfs_efd_log_item_t *efdp, | 359 | xfs_efd_item_format( |
392 | xfs_log_iovec_t *log_vector) | 360 | struct xfs_log_item *lip, |
361 | struct xfs_log_iovec *log_vector) | ||
393 | { | 362 | { |
394 | uint size; | 363 | struct xfs_efd_log_item *efdp = EFD_ITEM(lip); |
364 | uint size; | ||
395 | 365 | ||
396 | ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents); | 366 | ASSERT(efdp->efd_next_extent == efdp->efd_format.efd_nextents); |
397 | 367 | ||
@@ -401,48 +371,38 @@ xfs_efd_item_format(xfs_efd_log_item_t *efdp, | |||
401 | size += (efdp->efd_format.efd_nextents - 1) * sizeof(xfs_extent_t); | 371 | size += (efdp->efd_format.efd_nextents - 1) * sizeof(xfs_extent_t); |
402 | efdp->efd_format.efd_size = 1; | 372 | efdp->efd_format.efd_size = 1; |
403 | 373 | ||
404 | log_vector->i_addr = (xfs_caddr_t)&(efdp->efd_format); | 374 | log_vector->i_addr = &efdp->efd_format; |
405 | log_vector->i_len = size; | 375 | log_vector->i_len = size; |
406 | log_vector->i_type = XLOG_REG_TYPE_EFD_FORMAT; | 376 | log_vector->i_type = XLOG_REG_TYPE_EFD_FORMAT; |
407 | ASSERT(size >= sizeof(xfs_efd_log_format_t)); | 377 | ASSERT(size >= sizeof(xfs_efd_log_format_t)); |
408 | } | 378 | } |
409 | 379 | ||
410 | |||
411 | /* | 380 | /* |
412 | * Pinning has no meaning for an efd item, so just return. | 381 | * Pinning has no meaning for an efd item, so just return. |
413 | */ | 382 | */ |
414 | /*ARGSUSED*/ | ||
415 | STATIC void | 383 | STATIC void |
416 | xfs_efd_item_pin(xfs_efd_log_item_t *efdp) | 384 | xfs_efd_item_pin( |
385 | struct xfs_log_item *lip) | ||
417 | { | 386 | { |
418 | return; | ||
419 | } | 387 | } |
420 | 388 | ||
421 | |||
422 | /* | 389 | /* |
423 | * Since pinning has no meaning for an efd item, unpinning does | 390 | * Since pinning has no meaning for an efd item, unpinning does |
424 | * not either. | 391 | * not either. |
425 | */ | 392 | */ |
426 | /*ARGSUSED*/ | ||
427 | STATIC void | ||
428 | xfs_efd_item_unpin(xfs_efd_log_item_t *efdp) | ||
429 | { | ||
430 | return; | ||
431 | } | ||
432 | |||
433 | /*ARGSUSED*/ | ||
434 | STATIC void | 393 | STATIC void |
435 | xfs_efd_item_unpin_remove(xfs_efd_log_item_t *efdp, xfs_trans_t *tp) | 394 | xfs_efd_item_unpin( |
395 | struct xfs_log_item *lip, | ||
396 | int remove) | ||
436 | { | 397 | { |
437 | return; | ||
438 | } | 398 | } |
439 | 399 | ||
440 | /* | 400 | /* |
441 | * Efd items have no locking, so just return success. | 401 | * Efd items have no locking, so just return success. |
442 | */ | 402 | */ |
443 | /*ARGSUSED*/ | ||
444 | STATIC uint | 403 | STATIC uint |
445 | xfs_efd_item_trylock(xfs_efd_log_item_t *efdp) | 404 | xfs_efd_item_trylock( |
405 | struct xfs_log_item *lip) | ||
446 | { | 406 | { |
447 | return XFS_ITEM_LOCKED; | 407 | return XFS_ITEM_LOCKED; |
448 | } | 408 | } |
@@ -451,13 +411,12 @@ xfs_efd_item_trylock(xfs_efd_log_item_t *efdp) | |||
451 | * Efd items have no locking or pushing, so return failure | 411 | * Efd items have no locking or pushing, so return failure |
452 | * so that the caller doesn't bother with us. | 412 | * so that the caller doesn't bother with us. |
453 | */ | 413 | */ |
454 | /*ARGSUSED*/ | ||
455 | STATIC void | 414 | STATIC void |
456 | xfs_efd_item_unlock(xfs_efd_log_item_t *efdp) | 415 | xfs_efd_item_unlock( |
416 | struct xfs_log_item *lip) | ||
457 | { | 417 | { |
458 | if (efdp->efd_item.li_flags & XFS_LI_ABORTED) | 418 | if (lip->li_flags & XFS_LI_ABORTED) |
459 | xfs_efd_item_free(efdp); | 419 | xfs_efd_item_free(EFD_ITEM(lip)); |
460 | return; | ||
461 | } | 420 | } |
462 | 421 | ||
463 | /* | 422 | /* |
@@ -467,15 +426,18 @@ xfs_efd_item_unlock(xfs_efd_log_item_t *efdp) | |||
467 | * return -1 to keep the transaction code from further referencing | 426 | * return -1 to keep the transaction code from further referencing |
468 | * this item. | 427 | * this item. |
469 | */ | 428 | */ |
470 | /*ARGSUSED*/ | ||
471 | STATIC xfs_lsn_t | 429 | STATIC xfs_lsn_t |
472 | xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn) | 430 | xfs_efd_item_committed( |
431 | struct xfs_log_item *lip, | ||
432 | xfs_lsn_t lsn) | ||
473 | { | 433 | { |
434 | struct xfs_efd_log_item *efdp = EFD_ITEM(lip); | ||
435 | |||
474 | /* | 436 | /* |
475 | * If we got a log I/O error, it's always the case that the LR with the | 437 | * If we got a log I/O error, it's always the case that the LR with the |
476 | * EFI got unpinned and freed before the EFD got aborted. | 438 | * EFI got unpinned and freed before the EFD got aborted. |
477 | */ | 439 | */ |
478 | if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0) | 440 | if (!(lip->li_flags & XFS_LI_ABORTED)) |
479 | xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents); | 441 | xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents); |
480 | 442 | ||
481 | xfs_efd_item_free(efdp); | 443 | xfs_efd_item_free(efdp); |
@@ -486,11 +448,10 @@ xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn) | |||
486 | * There isn't much you can do to push on an efd item. It is simply | 448 | * There isn't much you can do to push on an efd item. It is simply |
487 | * stuck waiting for the log to be flushed to disk. | 449 | * stuck waiting for the log to be flushed to disk. |
488 | */ | 450 | */ |
489 | /*ARGSUSED*/ | ||
490 | STATIC void | 451 | STATIC void |
491 | xfs_efd_item_push(xfs_efd_log_item_t *efdp) | 452 | xfs_efd_item_push( |
453 | struct xfs_log_item *lip) | ||
492 | { | 454 | { |
493 | return; | ||
494 | } | 455 | } |
495 | 456 | ||
496 | /* | 457 | /* |
@@ -500,55 +461,48 @@ xfs_efd_item_push(xfs_efd_log_item_t *efdp) | |||
500 | * example, for inodes, the inode is locked throughout the extent freeing | 461 | * example, for inodes, the inode is locked throughout the extent freeing |
501 | * so the dependency should be recorded there. | 462 | * so the dependency should be recorded there. |
502 | */ | 463 | */ |
503 | /*ARGSUSED*/ | ||
504 | STATIC void | 464 | STATIC void |
505 | xfs_efd_item_committing(xfs_efd_log_item_t *efip, xfs_lsn_t lsn) | 465 | xfs_efd_item_committing( |
466 | struct xfs_log_item *lip, | ||
467 | xfs_lsn_t lsn) | ||
506 | { | 468 | { |
507 | return; | ||
508 | } | 469 | } |
509 | 470 | ||
510 | /* | 471 | /* |
511 | * This is the ops vector shared by all efd log items. | 472 | * This is the ops vector shared by all efd log items. |
512 | */ | 473 | */ |
513 | static struct xfs_item_ops xfs_efd_item_ops = { | 474 | static struct xfs_item_ops xfs_efd_item_ops = { |
514 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_efd_item_size, | 475 | .iop_size = xfs_efd_item_size, |
515 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 476 | .iop_format = xfs_efd_item_format, |
516 | xfs_efd_item_format, | 477 | .iop_pin = xfs_efd_item_pin, |
517 | .iop_pin = (void(*)(xfs_log_item_t*))xfs_efd_item_pin, | 478 | .iop_unpin = xfs_efd_item_unpin, |
518 | .iop_unpin = (void(*)(xfs_log_item_t*))xfs_efd_item_unpin, | 479 | .iop_trylock = xfs_efd_item_trylock, |
519 | .iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t*)) | 480 | .iop_unlock = xfs_efd_item_unlock, |
520 | xfs_efd_item_unpin_remove, | 481 | .iop_committed = xfs_efd_item_committed, |
521 | .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_efd_item_trylock, | 482 | .iop_push = xfs_efd_item_push, |
522 | .iop_unlock = (void(*)(xfs_log_item_t*))xfs_efd_item_unlock, | 483 | .iop_committing = xfs_efd_item_committing |
523 | .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
524 | xfs_efd_item_committed, | ||
525 | .iop_push = (void(*)(xfs_log_item_t*))xfs_efd_item_push, | ||
526 | .iop_pushbuf = NULL, | ||
527 | .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
528 | xfs_efd_item_committing | ||
529 | }; | 484 | }; |
530 | 485 | ||
531 | |||
532 | /* | 486 | /* |
533 | * Allocate and initialize an efd item with the given number of extents. | 487 | * Allocate and initialize an efd item with the given number of extents. |
534 | */ | 488 | */ |
535 | xfs_efd_log_item_t * | 489 | struct xfs_efd_log_item * |
536 | xfs_efd_init(xfs_mount_t *mp, | 490 | xfs_efd_init( |
537 | xfs_efi_log_item_t *efip, | 491 | struct xfs_mount *mp, |
538 | uint nextents) | 492 | struct xfs_efi_log_item *efip, |
493 | uint nextents) | ||
539 | 494 | ||
540 | { | 495 | { |
541 | xfs_efd_log_item_t *efdp; | 496 | struct xfs_efd_log_item *efdp; |
542 | uint size; | 497 | uint size; |
543 | 498 | ||
544 | ASSERT(nextents > 0); | 499 | ASSERT(nextents > 0); |
545 | if (nextents > XFS_EFD_MAX_FAST_EXTENTS) { | 500 | if (nextents > XFS_EFD_MAX_FAST_EXTENTS) { |
546 | size = (uint)(sizeof(xfs_efd_log_item_t) + | 501 | size = (uint)(sizeof(xfs_efd_log_item_t) + |
547 | ((nextents - 1) * sizeof(xfs_extent_t))); | 502 | ((nextents - 1) * sizeof(xfs_extent_t))); |
548 | efdp = (xfs_efd_log_item_t*)kmem_zalloc(size, KM_SLEEP); | 503 | efdp = kmem_zalloc(size, KM_SLEEP); |
549 | } else { | 504 | } else { |
550 | efdp = (xfs_efd_log_item_t*)kmem_zone_zalloc(xfs_efd_zone, | 505 | efdp = kmem_zone_zalloc(xfs_efd_zone, KM_SLEEP); |
551 | KM_SLEEP); | ||
552 | } | 506 | } |
553 | 507 | ||
554 | xfs_log_item_init(mp, &efdp->efd_item, XFS_LI_EFD, &xfs_efd_item_ops); | 508 | xfs_log_item_init(mp, &efdp->efd_item, XFS_LI_EFD, &xfs_efd_item_ops); |
@@ -556,5 +510,5 @@ xfs_efd_init(xfs_mount_t *mp, | |||
556 | efdp->efd_format.efd_nextents = nextents; | 510 | efdp->efd_format.efd_nextents = nextents; |
557 | efdp->efd_format.efd_efi_id = efip->efi_format.efi_id; | 511 | efdp->efd_format.efd_efi_id = efip->efi_format.efi_id; |
558 | 512 | ||
559 | return (efdp); | 513 | return efdp; |
560 | } | 514 | } |
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index 390850ee6603..9b715dce5699 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c | |||
@@ -18,13 +18,9 @@ | |||
18 | #include "xfs.h" | 18 | #include "xfs.h" |
19 | #include "xfs_bmap_btree.h" | 19 | #include "xfs_bmap_btree.h" |
20 | #include "xfs_inum.h" | 20 | #include "xfs_inum.h" |
21 | #include "xfs_dir2.h" | ||
22 | #include "xfs_dir2_sf.h" | ||
23 | #include "xfs_attr_sf.h" | ||
24 | #include "xfs_dinode.h" | 21 | #include "xfs_dinode.h" |
25 | #include "xfs_inode.h" | 22 | #include "xfs_inode.h" |
26 | #include "xfs_ag.h" | 23 | #include "xfs_ag.h" |
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_log.h" | 24 | #include "xfs_log.h" |
29 | #include "xfs_trans.h" | 25 | #include "xfs_trans.h" |
30 | #include "xfs_sb.h" | 26 | #include "xfs_sb.h" |
@@ -127,6 +123,82 @@ typedef struct fstrm_item | |||
127 | xfs_inode_t *pip; /* Parent directory inode pointer. */ | 123 | xfs_inode_t *pip; /* Parent directory inode pointer. */ |
128 | } fstrm_item_t; | 124 | } fstrm_item_t; |
129 | 125 | ||
126 | /* | ||
127 | * Allocation group filestream associations are tracked with per-ag atomic | ||
128 | * counters. These counters allow _xfs_filestream_pick_ag() to tell whether a | ||
129 | * particular AG already has active filestreams associated with it. The mount | ||
130 | * point's m_peraglock is used to protect these counters from per-ag array | ||
131 | * re-allocation during a growfs operation. When xfs_growfs_data_private() is | ||
132 | * about to reallocate the array, it calls xfs_filestream_flush() with the | ||
133 | * m_peraglock held in write mode. | ||
134 | * | ||
135 | * Since xfs_mru_cache_flush() guarantees that all the free functions for all | ||
136 | * the cache elements have finished executing before it returns, it's safe for | ||
137 | * the free functions to use the atomic counters without m_peraglock protection. | ||
138 | * This allows the implementation of xfs_fstrm_free_func() to be agnostic about | ||
139 | * whether it was called with the m_peraglock held in read mode, write mode or | ||
140 | * not held at all. The race condition this addresses is the following: | ||
141 | * | ||
142 | * - The work queue scheduler fires and pulls a filestream directory cache | ||
143 | * element off the LRU end of the cache for deletion, then gets pre-empted. | ||
144 | * - A growfs operation grabs the m_peraglock in write mode, flushes all the | ||
145 | * remaining items from the cache and reallocates the mount point's per-ag | ||
146 | * array, resetting all the counters to zero. | ||
147 | * - The work queue thread resumes and calls the free function for the element | ||
148 | * it started cleaning up earlier. In the process it decrements the | ||
149 | * filestreams counter for an AG that now has no references. | ||
150 | * | ||
151 | * With a shrinkfs feature, the above scenario could panic the system. | ||
152 | * | ||
153 | * All other uses of the following macros should be protected by either the | ||
154 | * m_peraglock held in read mode, or the cache's internal locking exposed by the | ||
155 | * interval between a call to xfs_mru_cache_lookup() and a call to | ||
156 | * xfs_mru_cache_done(). In addition, the m_peraglock must be held in read mode | ||
157 | * when new elements are added to the cache. | ||
158 | * | ||
159 | * Combined, these locking rules ensure that no associations will ever exist in | ||
160 | * the cache that reference per-ag array elements that have since been | ||
161 | * reallocated. | ||
162 | */ | ||
163 | static int | ||
164 | xfs_filestream_peek_ag( | ||
165 | xfs_mount_t *mp, | ||
166 | xfs_agnumber_t agno) | ||
167 | { | ||
168 | struct xfs_perag *pag; | ||
169 | int ret; | ||
170 | |||
171 | pag = xfs_perag_get(mp, agno); | ||
172 | ret = atomic_read(&pag->pagf_fstrms); | ||
173 | xfs_perag_put(pag); | ||
174 | return ret; | ||
175 | } | ||
176 | |||
177 | static int | ||
178 | xfs_filestream_get_ag( | ||
179 | xfs_mount_t *mp, | ||
180 | xfs_agnumber_t agno) | ||
181 | { | ||
182 | struct xfs_perag *pag; | ||
183 | int ret; | ||
184 | |||
185 | pag = xfs_perag_get(mp, agno); | ||
186 | ret = atomic_inc_return(&pag->pagf_fstrms); | ||
187 | xfs_perag_put(pag); | ||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | static void | ||
192 | xfs_filestream_put_ag( | ||
193 | xfs_mount_t *mp, | ||
194 | xfs_agnumber_t agno) | ||
195 | { | ||
196 | struct xfs_perag *pag; | ||
197 | |||
198 | pag = xfs_perag_get(mp, agno); | ||
199 | atomic_dec(&pag->pagf_fstrms); | ||
200 | xfs_perag_put(pag); | ||
201 | } | ||
130 | 202 | ||
131 | /* | 203 | /* |
132 | * Scan the AGs starting at startag looking for an AG that isn't in use and has | 204 | * Scan the AGs starting at startag looking for an AG that isn't in use and has |
@@ -355,16 +427,14 @@ xfs_fstrm_free_func( | |||
355 | { | 427 | { |
356 | fstrm_item_t *item = (fstrm_item_t *)data; | 428 | fstrm_item_t *item = (fstrm_item_t *)data; |
357 | xfs_inode_t *ip = item->ip; | 429 | xfs_inode_t *ip = item->ip; |
358 | int ref; | ||
359 | 430 | ||
360 | ASSERT(ip->i_ino == ino); | 431 | ASSERT(ip->i_ino == ino); |
361 | 432 | ||
362 | xfs_iflags_clear(ip, XFS_IFILESTREAM); | 433 | xfs_iflags_clear(ip, XFS_IFILESTREAM); |
363 | 434 | ||
364 | /* Drop the reference taken on the AG when the item was added. */ | 435 | /* Drop the reference taken on the AG when the item was added. */ |
365 | ref = xfs_filestream_put_ag(ip->i_mount, item->ag); | 436 | xfs_filestream_put_ag(ip->i_mount, item->ag); |
366 | 437 | ||
367 | ASSERT(ref >= 0); | ||
368 | TRACE_FREE(ip->i_mount, ip, item->pip, item->ag, | 438 | TRACE_FREE(ip->i_mount, ip, item->pip, item->ag, |
369 | xfs_filestream_peek_ag(ip->i_mount, item->ag)); | 439 | xfs_filestream_peek_ag(ip->i_mount, item->ag)); |
370 | 440 | ||
diff --git a/fs/xfs/xfs_filestream.h b/fs/xfs/xfs_filestream.h index 260f757bbc5d..09dd9af45434 100644 --- a/fs/xfs/xfs_filestream.h +++ b/fs/xfs/xfs_filestream.h | |||
@@ -42,88 +42,6 @@ extern ktrace_t *xfs_filestreams_trace_buf; | |||
42 | 42 | ||
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | /* | ||
46 | * Allocation group filestream associations are tracked with per-ag atomic | ||
47 | * counters. These counters allow _xfs_filestream_pick_ag() to tell whether a | ||
48 | * particular AG already has active filestreams associated with it. The mount | ||
49 | * point's m_peraglock is used to protect these counters from per-ag array | ||
50 | * re-allocation during a growfs operation. When xfs_growfs_data_private() is | ||
51 | * about to reallocate the array, it calls xfs_filestream_flush() with the | ||
52 | * m_peraglock held in write mode. | ||
53 | * | ||
54 | * Since xfs_mru_cache_flush() guarantees that all the free functions for all | ||
55 | * the cache elements have finished executing before it returns, it's safe for | ||
56 | * the free functions to use the atomic counters without m_peraglock protection. | ||
57 | * This allows the implementation of xfs_fstrm_free_func() to be agnostic about | ||
58 | * whether it was called with the m_peraglock held in read mode, write mode or | ||
59 | * not held at all. The race condition this addresses is the following: | ||
60 | * | ||
61 | * - The work queue scheduler fires and pulls a filestream directory cache | ||
62 | * element off the LRU end of the cache for deletion, then gets pre-empted. | ||
63 | * - A growfs operation grabs the m_peraglock in write mode, flushes all the | ||
64 | * remaining items from the cache and reallocates the mount point's per-ag | ||
65 | * array, resetting all the counters to zero. | ||
66 | * - The work queue thread resumes and calls the free function for the element | ||
67 | * it started cleaning up earlier. In the process it decrements the | ||
68 | * filestreams counter for an AG that now has no references. | ||
69 | * | ||
70 | * With a shrinkfs feature, the above scenario could panic the system. | ||
71 | * | ||
72 | * All other uses of the following macros should be protected by either the | ||
73 | * m_peraglock held in read mode, or the cache's internal locking exposed by the | ||
74 | * interval between a call to xfs_mru_cache_lookup() and a call to | ||
75 | * xfs_mru_cache_done(). In addition, the m_peraglock must be held in read mode | ||
76 | * when new elements are added to the cache. | ||
77 | * | ||
78 | * Combined, these locking rules ensure that no associations will ever exist in | ||
79 | * the cache that reference per-ag array elements that have since been | ||
80 | * reallocated. | ||
81 | */ | ||
82 | /* | ||
83 | * xfs_filestream_peek_ag is only used in tracing code | ||
84 | */ | ||
85 | static inline int | ||
86 | xfs_filestream_peek_ag( | ||
87 | xfs_mount_t *mp, | ||
88 | xfs_agnumber_t agno) | ||
89 | { | ||
90 | struct xfs_perag *pag; | ||
91 | int ret; | ||
92 | |||
93 | pag = xfs_perag_get(mp, agno); | ||
94 | ret = atomic_read(&pag->pagf_fstrms); | ||
95 | xfs_perag_put(pag); | ||
96 | return ret; | ||
97 | } | ||
98 | |||
99 | static inline int | ||
100 | xfs_filestream_get_ag( | ||
101 | xfs_mount_t *mp, | ||
102 | xfs_agnumber_t agno) | ||
103 | { | ||
104 | struct xfs_perag *pag; | ||
105 | int ret; | ||
106 | |||
107 | pag = xfs_perag_get(mp, agno); | ||
108 | ret = atomic_inc_return(&pag->pagf_fstrms); | ||
109 | xfs_perag_put(pag); | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static inline int | ||
114 | xfs_filestream_put_ag( | ||
115 | xfs_mount_t *mp, | ||
116 | xfs_agnumber_t agno) | ||
117 | { | ||
118 | struct xfs_perag *pag; | ||
119 | int ret; | ||
120 | |||
121 | pag = xfs_perag_get(mp, agno); | ||
122 | ret = atomic_dec_return(&pag->pagf_fstrms); | ||
123 | xfs_perag_put(pag); | ||
124 | return ret; | ||
125 | } | ||
126 | |||
127 | /* allocation selection flags */ | 45 | /* allocation selection flags */ |
128 | typedef enum xfs_fstrm_alloc { | 46 | typedef enum xfs_fstrm_alloc { |
129 | XFS_PICK_USERDATA = 1, | 47 | XFS_PICK_USERDATA = 1, |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 37a6f62c57b6..dbca5f5c37ba 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -24,14 +24,10 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
37 | #include "xfs_inode_item.h" | 33 | #include "xfs_inode_item.h" |
@@ -626,8 +622,7 @@ xfs_fs_log_dummy( | |||
626 | ip = mp->m_rootip; | 622 | ip = mp->m_rootip; |
627 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 623 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
628 | 624 | ||
629 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 625 | xfs_trans_ijoin(tp, ip); |
630 | xfs_trans_ihold(tp, ip); | ||
631 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 626 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
632 | xfs_trans_set_sync(tp); | 627 | xfs_trans_set_sync(tp); |
633 | error = xfs_trans_commit(tp, 0); | 628 | error = xfs_trans_commit(tp, 0); |
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index c7142a064c48..abf80ae1e95b 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -24,14 +24,10 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
37 | #include "xfs_btree.h" | 33 | #include "xfs_btree.h" |
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c index c282a9af5393..d352862cefa0 100644 --- a/fs/xfs/xfs_ialloc_btree.c +++ b/fs/xfs/xfs_ialloc_btree.c | |||
@@ -24,14 +24,10 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
37 | #include "xfs_btree.h" | 33 | #include "xfs_btree.h" |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 8f8b91be2c99..b1ecc6f97ade 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -25,14 +25,10 @@ | |||
25 | #include "xfs_trans.h" | 25 | #include "xfs_trans.h" |
26 | #include "xfs_sb.h" | 26 | #include "xfs_sb.h" |
27 | #include "xfs_ag.h" | 27 | #include "xfs_ag.h" |
28 | #include "xfs_dir2.h" | ||
29 | #include "xfs_dmapi.h" | ||
30 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 30 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 31 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
37 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
38 | #include "xfs_btree.h" | 34 | #include "xfs_btree.h" |
@@ -95,7 +91,7 @@ xfs_inode_alloc( | |||
95 | return ip; | 91 | return ip; |
96 | } | 92 | } |
97 | 93 | ||
98 | STATIC void | 94 | void |
99 | xfs_inode_free( | 95 | xfs_inode_free( |
100 | struct xfs_inode *ip) | 96 | struct xfs_inode *ip) |
101 | { | 97 | { |
@@ -212,7 +208,7 @@ xfs_iget_cache_hit( | |||
212 | ip->i_flags &= ~XFS_INEW; | 208 | ip->i_flags &= ~XFS_INEW; |
213 | ip->i_flags |= XFS_IRECLAIMABLE; | 209 | ip->i_flags |= XFS_IRECLAIMABLE; |
214 | __xfs_inode_set_reclaim_tag(pag, ip); | 210 | __xfs_inode_set_reclaim_tag(pag, ip); |
215 | trace_xfs_iget_reclaim(ip); | 211 | trace_xfs_iget_reclaim_fail(ip); |
216 | goto out_error; | 212 | goto out_error; |
217 | } | 213 | } |
218 | 214 | ||
@@ -227,6 +223,7 @@ xfs_iget_cache_hit( | |||
227 | } else { | 223 | } else { |
228 | /* If the VFS inode is being torn down, pause and try again. */ | 224 | /* If the VFS inode is being torn down, pause and try again. */ |
229 | if (!igrab(inode)) { | 225 | if (!igrab(inode)) { |
226 | trace_xfs_iget_skip(ip); | ||
230 | error = EAGAIN; | 227 | error = EAGAIN; |
231 | goto out_error; | 228 | goto out_error; |
232 | } | 229 | } |
@@ -234,6 +231,7 @@ xfs_iget_cache_hit( | |||
234 | /* We've got a live one. */ | 231 | /* We've got a live one. */ |
235 | spin_unlock(&ip->i_flags_lock); | 232 | spin_unlock(&ip->i_flags_lock); |
236 | read_unlock(&pag->pag_ici_lock); | 233 | read_unlock(&pag->pag_ici_lock); |
234 | trace_xfs_iget_hit(ip); | ||
237 | } | 235 | } |
238 | 236 | ||
239 | if (lock_flags != 0) | 237 | if (lock_flags != 0) |
@@ -242,7 +240,6 @@ xfs_iget_cache_hit( | |||
242 | xfs_iflags_clear(ip, XFS_ISTALE); | 240 | xfs_iflags_clear(ip, XFS_ISTALE); |
243 | XFS_STATS_INC(xs_ig_found); | 241 | XFS_STATS_INC(xs_ig_found); |
244 | 242 | ||
245 | trace_xfs_iget_found(ip); | ||
246 | return 0; | 243 | return 0; |
247 | 244 | ||
248 | out_error: | 245 | out_error: |
@@ -264,7 +261,6 @@ xfs_iget_cache_miss( | |||
264 | { | 261 | { |
265 | struct xfs_inode *ip; | 262 | struct xfs_inode *ip; |
266 | int error; | 263 | int error; |
267 | unsigned long first_index, mask; | ||
268 | xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino); | 264 | xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino); |
269 | 265 | ||
270 | ip = xfs_inode_alloc(mp, ino); | 266 | ip = xfs_inode_alloc(mp, ino); |
@@ -275,7 +271,7 @@ xfs_iget_cache_miss( | |||
275 | if (error) | 271 | if (error) |
276 | goto out_destroy; | 272 | goto out_destroy; |
277 | 273 | ||
278 | xfs_itrace_entry(ip); | 274 | trace_xfs_iget_miss(ip); |
279 | 275 | ||
280 | if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) { | 276 | if ((ip->i_d.di_mode == 0) && !(flags & XFS_IGET_CREATE)) { |
281 | error = ENOENT; | 277 | error = ENOENT; |
@@ -301,8 +297,6 @@ xfs_iget_cache_miss( | |||
301 | BUG(); | 297 | BUG(); |
302 | } | 298 | } |
303 | 299 | ||
304 | mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1); | ||
305 | first_index = agino & mask; | ||
306 | write_lock(&pag->pag_ici_lock); | 300 | write_lock(&pag->pag_ici_lock); |
307 | 301 | ||
308 | /* insert the new inode */ | 302 | /* insert the new inode */ |
@@ -321,7 +315,6 @@ xfs_iget_cache_miss( | |||
321 | write_unlock(&pag->pag_ici_lock); | 315 | write_unlock(&pag->pag_ici_lock); |
322 | radix_tree_preload_end(); | 316 | radix_tree_preload_end(); |
323 | 317 | ||
324 | trace_xfs_iget_alloc(ip); | ||
325 | *ipp = ip; | 318 | *ipp = ip; |
326 | return 0; | 319 | return 0; |
327 | 320 | ||
@@ -422,97 +415,6 @@ out_error_or_again: | |||
422 | } | 415 | } |
423 | 416 | ||
424 | /* | 417 | /* |
425 | * Decrement reference count of an inode structure and unlock it. | ||
426 | * | ||
427 | * ip -- the inode being released | ||
428 | * lock_flags -- this parameter indicates the inode's locks to be | ||
429 | * to be released. See the comment on xfs_iunlock() for a list | ||
430 | * of valid values. | ||
431 | */ | ||
432 | void | ||
433 | xfs_iput(xfs_inode_t *ip, | ||
434 | uint lock_flags) | ||
435 | { | ||
436 | xfs_itrace_entry(ip); | ||
437 | xfs_iunlock(ip, lock_flags); | ||
438 | IRELE(ip); | ||
439 | } | ||
440 | |||
441 | /* | ||
442 | * Special iput for brand-new inodes that are still locked | ||
443 | */ | ||
444 | void | ||
445 | xfs_iput_new( | ||
446 | xfs_inode_t *ip, | ||
447 | uint lock_flags) | ||
448 | { | ||
449 | struct inode *inode = VFS_I(ip); | ||
450 | |||
451 | xfs_itrace_entry(ip); | ||
452 | |||
453 | if ((ip->i_d.di_mode == 0)) { | ||
454 | ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE)); | ||
455 | make_bad_inode(inode); | ||
456 | } | ||
457 | if (inode->i_state & I_NEW) | ||
458 | unlock_new_inode(inode); | ||
459 | if (lock_flags) | ||
460 | xfs_iunlock(ip, lock_flags); | ||
461 | IRELE(ip); | ||
462 | } | ||
463 | |||
464 | /* | ||
465 | * This is called free all the memory associated with an inode. | ||
466 | * It must free the inode itself and any buffers allocated for | ||
467 | * if_extents/if_data and if_broot. It must also free the lock | ||
468 | * associated with the inode. | ||
469 | * | ||
470 | * Note: because we don't initialise everything on reallocation out | ||
471 | * of the zone, we must ensure we nullify everything correctly before | ||
472 | * freeing the structure. | ||
473 | */ | ||
474 | void | ||
475 | xfs_ireclaim( | ||
476 | struct xfs_inode *ip) | ||
477 | { | ||
478 | struct xfs_mount *mp = ip->i_mount; | ||
479 | struct xfs_perag *pag; | ||
480 | xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); | ||
481 | |||
482 | XFS_STATS_INC(xs_ig_reclaims); | ||
483 | |||
484 | /* | ||
485 | * Remove the inode from the per-AG radix tree. | ||
486 | * | ||
487 | * Because radix_tree_delete won't complain even if the item was never | ||
488 | * added to the tree assert that it's been there before to catch | ||
489 | * problems with the inode life time early on. | ||
490 | */ | ||
491 | pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); | ||
492 | write_lock(&pag->pag_ici_lock); | ||
493 | if (!radix_tree_delete(&pag->pag_ici_root, agino)) | ||
494 | ASSERT(0); | ||
495 | write_unlock(&pag->pag_ici_lock); | ||
496 | xfs_perag_put(pag); | ||
497 | |||
498 | /* | ||
499 | * Here we do an (almost) spurious inode lock in order to coordinate | ||
500 | * with inode cache radix tree lookups. This is because the lookup | ||
501 | * can reference the inodes in the cache without taking references. | ||
502 | * | ||
503 | * We make that OK here by ensuring that we wait until the inode is | ||
504 | * unlocked after the lookup before we go ahead and free it. We get | ||
505 | * both the ilock and the iolock because the code may need to drop the | ||
506 | * ilock one but will still hold the iolock. | ||
507 | */ | ||
508 | xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
509 | xfs_qm_dqdetach(ip); | ||
510 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
511 | |||
512 | xfs_inode_free(ip); | ||
513 | } | ||
514 | |||
515 | /* | ||
516 | * This is a wrapper routine around the xfs_ilock() routine | 418 | * This is a wrapper routine around the xfs_ilock() routine |
517 | * used to centralize some grungy code. It is used in places | 419 | * used to centralize some grungy code. It is used in places |
518 | * that wish to lock the inode solely for reading the extents. | 420 | * that wish to lock the inode solely for reading the extents. |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index b76a829d7e20..68415cb4f23c 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -27,13 +27,10 @@ | |||
27 | #include "xfs_trans_priv.h" | 27 | #include "xfs_trans_priv.h" |
28 | #include "xfs_sb.h" | 28 | #include "xfs_sb.h" |
29 | #include "xfs_ag.h" | 29 | #include "xfs_ag.h" |
30 | #include "xfs_dir2.h" | ||
31 | #include "xfs_dmapi.h" | ||
32 | #include "xfs_mount.h" | 30 | #include "xfs_mount.h" |
33 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
34 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
35 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
36 | #include "xfs_dir2_sf.h" | ||
37 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
39 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
@@ -44,7 +41,6 @@ | |||
44 | #include "xfs_alloc.h" | 41 | #include "xfs_alloc.h" |
45 | #include "xfs_ialloc.h" | 42 | #include "xfs_ialloc.h" |
46 | #include "xfs_bmap.h" | 43 | #include "xfs_bmap.h" |
47 | #include "xfs_rw.h" | ||
48 | #include "xfs_error.h" | 44 | #include "xfs_error.h" |
49 | #include "xfs_utils.h" | 45 | #include "xfs_utils.h" |
50 | #include "xfs_quota.h" | 46 | #include "xfs_quota.h" |
@@ -426,7 +422,7 @@ xfs_iformat( | |||
426 | if (!XFS_DFORK_Q(dip)) | 422 | if (!XFS_DFORK_Q(dip)) |
427 | return 0; | 423 | return 0; |
428 | ASSERT(ip->i_afp == NULL); | 424 | ASSERT(ip->i_afp == NULL); |
429 | ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP); | 425 | ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP | KM_NOFS); |
430 | ip->i_afp->if_ext_max = | 426 | ip->i_afp->if_ext_max = |
431 | XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t); | 427 | XFS_IFORK_ASIZE(ip) / (uint)sizeof(xfs_bmbt_rec_t); |
432 | switch (dip->di_aformat) { | 428 | switch (dip->di_aformat) { |
@@ -509,7 +505,7 @@ xfs_iformat_local( | |||
509 | ifp->if_u1.if_data = ifp->if_u2.if_inline_data; | 505 | ifp->if_u1.if_data = ifp->if_u2.if_inline_data; |
510 | else { | 506 | else { |
511 | real_size = roundup(size, 4); | 507 | real_size = roundup(size, 4); |
512 | ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP); | 508 | ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS); |
513 | } | 509 | } |
514 | ifp->if_bytes = size; | 510 | ifp->if_bytes = size; |
515 | ifp->if_real_bytes = real_size; | 511 | ifp->if_real_bytes = real_size; |
@@ -636,7 +632,7 @@ xfs_iformat_btree( | |||
636 | } | 632 | } |
637 | 633 | ||
638 | ifp->if_broot_bytes = size; | 634 | ifp->if_broot_bytes = size; |
639 | ifp->if_broot = kmem_alloc(size, KM_SLEEP); | 635 | ifp->if_broot = kmem_alloc(size, KM_SLEEP | KM_NOFS); |
640 | ASSERT(ifp->if_broot != NULL); | 636 | ASSERT(ifp->if_broot != NULL); |
641 | /* | 637 | /* |
642 | * Copy and convert from the on-disk structure | 638 | * Copy and convert from the on-disk structure |
@@ -922,7 +918,6 @@ xfs_iread_extents( | |||
922 | int error; | 918 | int error; |
923 | xfs_ifork_t *ifp; | 919 | xfs_ifork_t *ifp; |
924 | xfs_extnum_t nextents; | 920 | xfs_extnum_t nextents; |
925 | size_t size; | ||
926 | 921 | ||
927 | if (unlikely(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) { | 922 | if (unlikely(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE)) { |
928 | XFS_ERROR_REPORT("xfs_iread_extents", XFS_ERRLEVEL_LOW, | 923 | XFS_ERROR_REPORT("xfs_iread_extents", XFS_ERRLEVEL_LOW, |
@@ -930,7 +925,6 @@ xfs_iread_extents( | |||
930 | return XFS_ERROR(EFSCORRUPTED); | 925 | return XFS_ERROR(EFSCORRUPTED); |
931 | } | 926 | } |
932 | nextents = XFS_IFORK_NEXTENTS(ip, whichfork); | 927 | nextents = XFS_IFORK_NEXTENTS(ip, whichfork); |
933 | size = nextents * sizeof(xfs_bmbt_rec_t); | ||
934 | ifp = XFS_IFORK_PTR(ip, whichfork); | 928 | ifp = XFS_IFORK_PTR(ip, whichfork); |
935 | 929 | ||
936 | /* | 930 | /* |
@@ -1226,7 +1220,7 @@ xfs_isize_check( | |||
1226 | (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - | 1220 | (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - |
1227 | map_first), | 1221 | map_first), |
1228 | XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps, | 1222 | XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps, |
1229 | NULL, NULL)) | 1223 | NULL)) |
1230 | return; | 1224 | return; |
1231 | ASSERT(nimaps == 1); | 1225 | ASSERT(nimaps == 1); |
1232 | ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK); | 1226 | ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK); |
@@ -1460,7 +1454,7 @@ xfs_itruncate_finish( | |||
1460 | ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); | 1454 | ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); |
1461 | ASSERT(ip->i_transp == *tp); | 1455 | ASSERT(ip->i_transp == *tp); |
1462 | ASSERT(ip->i_itemp != NULL); | 1456 | ASSERT(ip->i_itemp != NULL); |
1463 | ASSERT(ip->i_itemp->ili_flags & XFS_ILI_HOLD); | 1457 | ASSERT(ip->i_itemp->ili_lock_flags == 0); |
1464 | 1458 | ||
1465 | 1459 | ||
1466 | ntp = *tp; | 1460 | ntp = *tp; |
@@ -1589,11 +1583,10 @@ xfs_itruncate_finish( | |||
1589 | xfs_bmap_init(&free_list, &first_block); | 1583 | xfs_bmap_init(&free_list, &first_block); |
1590 | error = xfs_bunmapi(ntp, ip, | 1584 | error = xfs_bunmapi(ntp, ip, |
1591 | first_unmap_block, unmap_len, | 1585 | first_unmap_block, unmap_len, |
1592 | xfs_bmapi_aflag(fork) | | 1586 | xfs_bmapi_aflag(fork), |
1593 | (sync ? 0 : XFS_BMAPI_ASYNC), | ||
1594 | XFS_ITRUNC_MAX_EXTENTS, | 1587 | XFS_ITRUNC_MAX_EXTENTS, |
1595 | &first_block, &free_list, | 1588 | &first_block, &free_list, |
1596 | NULL, &done); | 1589 | &done); |
1597 | if (error) { | 1590 | if (error) { |
1598 | /* | 1591 | /* |
1599 | * If the bunmapi call encounters an error, | 1592 | * If the bunmapi call encounters an error, |
@@ -1612,12 +1605,8 @@ xfs_itruncate_finish( | |||
1612 | */ | 1605 | */ |
1613 | error = xfs_bmap_finish(tp, &free_list, &committed); | 1606 | error = xfs_bmap_finish(tp, &free_list, &committed); |
1614 | ntp = *tp; | 1607 | ntp = *tp; |
1615 | if (committed) { | 1608 | if (committed) |
1616 | /* link the inode into the next xact in the chain */ | 1609 | xfs_trans_ijoin(ntp, ip); |
1617 | xfs_trans_ijoin(ntp, ip, | ||
1618 | XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
1619 | xfs_trans_ihold(ntp, ip); | ||
1620 | } | ||
1621 | 1610 | ||
1622 | if (error) { | 1611 | if (error) { |
1623 | /* | 1612 | /* |
@@ -1646,9 +1635,7 @@ xfs_itruncate_finish( | |||
1646 | error = xfs_trans_commit(*tp, 0); | 1635 | error = xfs_trans_commit(*tp, 0); |
1647 | *tp = ntp; | 1636 | *tp = ntp; |
1648 | 1637 | ||
1649 | /* link the inode into the next transaction in the chain */ | 1638 | xfs_trans_ijoin(ntp, ip); |
1650 | xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
1651 | xfs_trans_ihold(ntp, ip); | ||
1652 | 1639 | ||
1653 | if (error) | 1640 | if (error) |
1654 | return error; | 1641 | return error; |
@@ -1985,7 +1972,7 @@ xfs_ifree_cluster( | |||
1985 | if (lip->li_type == XFS_LI_INODE) { | 1972 | if (lip->li_type == XFS_LI_INODE) { |
1986 | iip = (xfs_inode_log_item_t *)lip; | 1973 | iip = (xfs_inode_log_item_t *)lip; |
1987 | ASSERT(iip->ili_logged == 1); | 1974 | ASSERT(iip->ili_logged == 1); |
1988 | lip->li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_istale_done; | 1975 | lip->li_cb = xfs_istale_done; |
1989 | xfs_trans_ail_copy_lsn(mp->m_ail, | 1976 | xfs_trans_ail_copy_lsn(mp->m_ail, |
1990 | &iip->ili_flush_lsn, | 1977 | &iip->ili_flush_lsn, |
1991 | &iip->ili_item.li_lsn); | 1978 | &iip->ili_item.li_lsn); |
@@ -2055,9 +2042,8 @@ xfs_ifree_cluster( | |||
2055 | xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn, | 2042 | xfs_trans_ail_copy_lsn(mp->m_ail, &iip->ili_flush_lsn, |
2056 | &iip->ili_item.li_lsn); | 2043 | &iip->ili_item.li_lsn); |
2057 | 2044 | ||
2058 | xfs_buf_attach_iodone(bp, | 2045 | xfs_buf_attach_iodone(bp, xfs_istale_done, |
2059 | (void(*)(xfs_buf_t*,xfs_log_item_t*)) | 2046 | &iip->ili_item); |
2060 | xfs_istale_done, (xfs_log_item_t *)iip); | ||
2061 | 2047 | ||
2062 | if (ip != free_ip) | 2048 | if (ip != free_ip) |
2063 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 2049 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
@@ -2203,7 +2189,7 @@ xfs_iroot_realloc( | |||
2203 | */ | 2189 | */ |
2204 | if (ifp->if_broot_bytes == 0) { | 2190 | if (ifp->if_broot_bytes == 0) { |
2205 | new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(rec_diff); | 2191 | new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(rec_diff); |
2206 | ifp->if_broot = kmem_alloc(new_size, KM_SLEEP); | 2192 | ifp->if_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS); |
2207 | ifp->if_broot_bytes = (int)new_size; | 2193 | ifp->if_broot_bytes = (int)new_size; |
2208 | return; | 2194 | return; |
2209 | } | 2195 | } |
@@ -2219,7 +2205,7 @@ xfs_iroot_realloc( | |||
2219 | new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max); | 2205 | new_size = (size_t)XFS_BMAP_BROOT_SPACE_CALC(new_max); |
2220 | ifp->if_broot = kmem_realloc(ifp->if_broot, new_size, | 2206 | ifp->if_broot = kmem_realloc(ifp->if_broot, new_size, |
2221 | (size_t)XFS_BMAP_BROOT_SPACE_CALC(cur_max), /* old size */ | 2207 | (size_t)XFS_BMAP_BROOT_SPACE_CALC(cur_max), /* old size */ |
2222 | KM_SLEEP); | 2208 | KM_SLEEP | KM_NOFS); |
2223 | op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, | 2209 | op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, |
2224 | ifp->if_broot_bytes); | 2210 | ifp->if_broot_bytes); |
2225 | np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, | 2211 | np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, |
@@ -2245,7 +2231,7 @@ xfs_iroot_realloc( | |||
2245 | else | 2231 | else |
2246 | new_size = 0; | 2232 | new_size = 0; |
2247 | if (new_size > 0) { | 2233 | if (new_size > 0) { |
2248 | new_broot = kmem_alloc(new_size, KM_SLEEP); | 2234 | new_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS); |
2249 | /* | 2235 | /* |
2250 | * First copy over the btree block header. | 2236 | * First copy over the btree block header. |
2251 | */ | 2237 | */ |
@@ -2349,7 +2335,8 @@ xfs_idata_realloc( | |||
2349 | real_size = roundup(new_size, 4); | 2335 | real_size = roundup(new_size, 4); |
2350 | if (ifp->if_u1.if_data == NULL) { | 2336 | if (ifp->if_u1.if_data == NULL) { |
2351 | ASSERT(ifp->if_real_bytes == 0); | 2337 | ASSERT(ifp->if_real_bytes == 0); |
2352 | ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP); | 2338 | ifp->if_u1.if_data = kmem_alloc(real_size, |
2339 | KM_SLEEP | KM_NOFS); | ||
2353 | } else if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) { | 2340 | } else if (ifp->if_u1.if_data != ifp->if_u2.if_inline_data) { |
2354 | /* | 2341 | /* |
2355 | * Only do the realloc if the underlying size | 2342 | * Only do the realloc if the underlying size |
@@ -2360,11 +2347,12 @@ xfs_idata_realloc( | |||
2360 | kmem_realloc(ifp->if_u1.if_data, | 2347 | kmem_realloc(ifp->if_u1.if_data, |
2361 | real_size, | 2348 | real_size, |
2362 | ifp->if_real_bytes, | 2349 | ifp->if_real_bytes, |
2363 | KM_SLEEP); | 2350 | KM_SLEEP | KM_NOFS); |
2364 | } | 2351 | } |
2365 | } else { | 2352 | } else { |
2366 | ASSERT(ifp->if_real_bytes == 0); | 2353 | ASSERT(ifp->if_real_bytes == 0); |
2367 | ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP); | 2354 | ifp->if_u1.if_data = kmem_alloc(real_size, |
2355 | KM_SLEEP | KM_NOFS); | ||
2368 | memcpy(ifp->if_u1.if_data, ifp->if_u2.if_inline_data, | 2356 | memcpy(ifp->if_u1.if_data, ifp->if_u2.if_inline_data, |
2369 | ifp->if_bytes); | 2357 | ifp->if_bytes); |
2370 | } | 2358 | } |
@@ -2731,7 +2719,6 @@ cluster_corrupt_out: | |||
2731 | * mark it as stale and brelse. | 2719 | * mark it as stale and brelse. |
2732 | */ | 2720 | */ |
2733 | if (XFS_BUF_IODONE_FUNC(bp)) { | 2721 | if (XFS_BUF_IODONE_FUNC(bp)) { |
2734 | XFS_BUF_CLR_BDSTRAT_FUNC(bp); | ||
2735 | XFS_BUF_UNDONE(bp); | 2722 | XFS_BUF_UNDONE(bp); |
2736 | XFS_BUF_STALE(bp); | 2723 | XFS_BUF_STALE(bp); |
2737 | XFS_BUF_ERROR(bp,EIO); | 2724 | XFS_BUF_ERROR(bp,EIO); |
@@ -3069,8 +3056,7 @@ xfs_iflush_int( | |||
3069 | * and unlock the inode's flush lock when the inode is | 3056 | * and unlock the inode's flush lock when the inode is |
3070 | * completely written to disk. | 3057 | * completely written to disk. |
3071 | */ | 3058 | */ |
3072 | xfs_buf_attach_iodone(bp, (void(*)(xfs_buf_t*,xfs_log_item_t*)) | 3059 | xfs_buf_attach_iodone(bp, xfs_iflush_done, &iip->ili_item); |
3073 | xfs_iflush_done, (xfs_log_item_t *)iip); | ||
3074 | 3060 | ||
3075 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); | 3061 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); |
3076 | ASSERT(XFS_BUF_IODONE_FUNC(bp) != NULL); | 3062 | ASSERT(XFS_BUF_IODONE_FUNC(bp) != NULL); |
@@ -3514,13 +3500,11 @@ xfs_iext_remove_indirect( | |||
3514 | xfs_extnum_t ext_diff; /* extents to remove in current list */ | 3500 | xfs_extnum_t ext_diff; /* extents to remove in current list */ |
3515 | xfs_extnum_t nex1; /* number of extents before idx */ | 3501 | xfs_extnum_t nex1; /* number of extents before idx */ |
3516 | xfs_extnum_t nex2; /* extents after idx + count */ | 3502 | xfs_extnum_t nex2; /* extents after idx + count */ |
3517 | int nlists; /* entries in indirection array */ | ||
3518 | int page_idx = idx; /* index in target extent list */ | 3503 | int page_idx = idx; /* index in target extent list */ |
3519 | 3504 | ||
3520 | ASSERT(ifp->if_flags & XFS_IFEXTIREC); | 3505 | ASSERT(ifp->if_flags & XFS_IFEXTIREC); |
3521 | erp = xfs_iext_idx_to_irec(ifp, &page_idx, &erp_idx, 0); | 3506 | erp = xfs_iext_idx_to_irec(ifp, &page_idx, &erp_idx, 0); |
3522 | ASSERT(erp != NULL); | 3507 | ASSERT(erp != NULL); |
3523 | nlists = ifp->if_real_bytes / XFS_IEXT_BUFSZ; | ||
3524 | nex1 = page_idx; | 3508 | nex1 = page_idx; |
3525 | ext_cnt = count; | 3509 | ext_cnt = count; |
3526 | while (ext_cnt) { | 3510 | while (ext_cnt) { |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 78550df13cd6..0898c5417d12 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -443,8 +443,6 @@ static inline void xfs_ifunlock(xfs_inode_t *ip) | |||
443 | */ | 443 | */ |
444 | int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, | 444 | int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, |
445 | uint, uint, xfs_inode_t **); | 445 | uint, uint, xfs_inode_t **); |
446 | void xfs_iput(xfs_inode_t *, uint); | ||
447 | void xfs_iput_new(xfs_inode_t *, uint); | ||
448 | void xfs_ilock(xfs_inode_t *, uint); | 446 | void xfs_ilock(xfs_inode_t *, uint); |
449 | int xfs_ilock_nowait(xfs_inode_t *, uint); | 447 | int xfs_ilock_nowait(xfs_inode_t *, uint); |
450 | void xfs_iunlock(xfs_inode_t *, uint); | 448 | void xfs_iunlock(xfs_inode_t *, uint); |
@@ -452,7 +450,7 @@ void xfs_ilock_demote(xfs_inode_t *, uint); | |||
452 | int xfs_isilocked(xfs_inode_t *, uint); | 450 | int xfs_isilocked(xfs_inode_t *, uint); |
453 | uint xfs_ilock_map_shared(xfs_inode_t *); | 451 | uint xfs_ilock_map_shared(xfs_inode_t *); |
454 | void xfs_iunlock_map_shared(xfs_inode_t *, uint); | 452 | void xfs_iunlock_map_shared(xfs_inode_t *, uint); |
455 | void xfs_ireclaim(xfs_inode_t *); | 453 | void xfs_inode_free(struct xfs_inode *ip); |
456 | 454 | ||
457 | /* | 455 | /* |
458 | * xfs_inode.c prototypes. | 456 | * xfs_inode.c prototypes. |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index cf8249a60004..fe00777e2796 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -22,30 +22,26 @@ | |||
22 | #include "xfs_log.h" | 22 | #include "xfs_log.h" |
23 | #include "xfs_inum.h" | 23 | #include "xfs_inum.h" |
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_buf_item.h" | ||
26 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
27 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
28 | #include "xfs_dir2.h" | ||
29 | #include "xfs_dmapi.h" | ||
30 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
31 | #include "xfs_trans_priv.h" | 28 | #include "xfs_trans_priv.h" |
32 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | ||
34 | #include "xfs_ialloc_btree.h" | ||
35 | #include "xfs_dir2_sf.h" | ||
36 | #include "xfs_attr_sf.h" | ||
37 | #include "xfs_dinode.h" | 30 | #include "xfs_dinode.h" |
38 | #include "xfs_inode.h" | 31 | #include "xfs_inode.h" |
39 | #include "xfs_inode_item.h" | 32 | #include "xfs_inode_item.h" |
40 | #include "xfs_btree.h" | ||
41 | #include "xfs_ialloc.h" | ||
42 | #include "xfs_rw.h" | ||
43 | #include "xfs_error.h" | 33 | #include "xfs_error.h" |
44 | #include "xfs_trace.h" | 34 | #include "xfs_trace.h" |
45 | 35 | ||
46 | 36 | ||
47 | kmem_zone_t *xfs_ili_zone; /* inode log item zone */ | 37 | kmem_zone_t *xfs_ili_zone; /* inode log item zone */ |
48 | 38 | ||
39 | static inline struct xfs_inode_log_item *INODE_ITEM(struct xfs_log_item *lip) | ||
40 | { | ||
41 | return container_of(lip, struct xfs_inode_log_item, ili_item); | ||
42 | } | ||
43 | |||
44 | |||
49 | /* | 45 | /* |
50 | * This returns the number of iovecs needed to log the given inode item. | 46 | * This returns the number of iovecs needed to log the given inode item. |
51 | * | 47 | * |
@@ -55,13 +51,11 @@ kmem_zone_t *xfs_ili_zone; /* inode log item zone */ | |||
55 | */ | 51 | */ |
56 | STATIC uint | 52 | STATIC uint |
57 | xfs_inode_item_size( | 53 | xfs_inode_item_size( |
58 | xfs_inode_log_item_t *iip) | 54 | struct xfs_log_item *lip) |
59 | { | 55 | { |
60 | uint nvecs; | 56 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); |
61 | xfs_inode_t *ip; | 57 | struct xfs_inode *ip = iip->ili_inode; |
62 | 58 | uint nvecs = 2; | |
63 | ip = iip->ili_inode; | ||
64 | nvecs = 2; | ||
65 | 59 | ||
66 | /* | 60 | /* |
67 | * Only log the data/extents/b-tree root if there is something | 61 | * Only log the data/extents/b-tree root if there is something |
@@ -212,21 +206,17 @@ xfs_inode_item_size( | |||
212 | */ | 206 | */ |
213 | STATIC void | 207 | STATIC void |
214 | xfs_inode_item_format( | 208 | xfs_inode_item_format( |
215 | xfs_inode_log_item_t *iip, | 209 | struct xfs_log_item *lip, |
216 | xfs_log_iovec_t *log_vector) | 210 | struct xfs_log_iovec *vecp) |
217 | { | 211 | { |
212 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); | ||
213 | struct xfs_inode *ip = iip->ili_inode; | ||
218 | uint nvecs; | 214 | uint nvecs; |
219 | xfs_log_iovec_t *vecp; | ||
220 | xfs_inode_t *ip; | ||
221 | size_t data_bytes; | 215 | size_t data_bytes; |
222 | xfs_bmbt_rec_t *ext_buffer; | 216 | xfs_bmbt_rec_t *ext_buffer; |
223 | int nrecs; | ||
224 | xfs_mount_t *mp; | 217 | xfs_mount_t *mp; |
225 | 218 | ||
226 | ip = iip->ili_inode; | 219 | vecp->i_addr = &iip->ili_format; |
227 | vecp = log_vector; | ||
228 | |||
229 | vecp->i_addr = (xfs_caddr_t)&iip->ili_format; | ||
230 | vecp->i_len = sizeof(xfs_inode_log_format_t); | 220 | vecp->i_len = sizeof(xfs_inode_log_format_t); |
231 | vecp->i_type = XLOG_REG_TYPE_IFORMAT; | 221 | vecp->i_type = XLOG_REG_TYPE_IFORMAT; |
232 | vecp++; | 222 | vecp++; |
@@ -277,7 +267,7 @@ xfs_inode_item_format( | |||
277 | */ | 267 | */ |
278 | xfs_synchronize_times(ip); | 268 | xfs_synchronize_times(ip); |
279 | 269 | ||
280 | vecp->i_addr = (xfs_caddr_t)&ip->i_d; | 270 | vecp->i_addr = &ip->i_d; |
281 | vecp->i_len = sizeof(struct xfs_icdinode); | 271 | vecp->i_len = sizeof(struct xfs_icdinode); |
282 | vecp->i_type = XLOG_REG_TYPE_ICORE; | 272 | vecp->i_type = XLOG_REG_TYPE_ICORE; |
283 | vecp++; | 273 | vecp++; |
@@ -323,18 +313,17 @@ xfs_inode_item_format( | |||
323 | ASSERT(ip->i_df.if_u1.if_extents != NULL); | 313 | ASSERT(ip->i_df.if_u1.if_extents != NULL); |
324 | ASSERT(ip->i_d.di_nextents > 0); | 314 | ASSERT(ip->i_d.di_nextents > 0); |
325 | ASSERT(iip->ili_extents_buf == NULL); | 315 | ASSERT(iip->ili_extents_buf == NULL); |
326 | nrecs = ip->i_df.if_bytes / | 316 | ASSERT((ip->i_df.if_bytes / |
327 | (uint)sizeof(xfs_bmbt_rec_t); | 317 | (uint)sizeof(xfs_bmbt_rec_t)) > 0); |
328 | ASSERT(nrecs > 0); | ||
329 | #ifdef XFS_NATIVE_HOST | 318 | #ifdef XFS_NATIVE_HOST |
330 | if (nrecs == ip->i_d.di_nextents) { | 319 | if (ip->i_d.di_nextents == ip->i_df.if_bytes / |
320 | (uint)sizeof(xfs_bmbt_rec_t)) { | ||
331 | /* | 321 | /* |
332 | * There are no delayed allocation | 322 | * There are no delayed allocation |
333 | * extents, so just point to the | 323 | * extents, so just point to the |
334 | * real extents array. | 324 | * real extents array. |
335 | */ | 325 | */ |
336 | vecp->i_addr = | 326 | vecp->i_addr = ip->i_df.if_u1.if_extents; |
337 | (char *)(ip->i_df.if_u1.if_extents); | ||
338 | vecp->i_len = ip->i_df.if_bytes; | 327 | vecp->i_len = ip->i_df.if_bytes; |
339 | vecp->i_type = XLOG_REG_TYPE_IEXT; | 328 | vecp->i_type = XLOG_REG_TYPE_IEXT; |
340 | } else | 329 | } else |
@@ -352,7 +341,7 @@ xfs_inode_item_format( | |||
352 | ext_buffer = kmem_alloc(ip->i_df.if_bytes, | 341 | ext_buffer = kmem_alloc(ip->i_df.if_bytes, |
353 | KM_SLEEP); | 342 | KM_SLEEP); |
354 | iip->ili_extents_buf = ext_buffer; | 343 | iip->ili_extents_buf = ext_buffer; |
355 | vecp->i_addr = (xfs_caddr_t)ext_buffer; | 344 | vecp->i_addr = ext_buffer; |
356 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, | 345 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, |
357 | XFS_DATA_FORK); | 346 | XFS_DATA_FORK); |
358 | vecp->i_type = XLOG_REG_TYPE_IEXT; | 347 | vecp->i_type = XLOG_REG_TYPE_IEXT; |
@@ -371,7 +360,7 @@ xfs_inode_item_format( | |||
371 | if (iip->ili_format.ilf_fields & XFS_ILOG_DBROOT) { | 360 | if (iip->ili_format.ilf_fields & XFS_ILOG_DBROOT) { |
372 | ASSERT(ip->i_df.if_broot_bytes > 0); | 361 | ASSERT(ip->i_df.if_broot_bytes > 0); |
373 | ASSERT(ip->i_df.if_broot != NULL); | 362 | ASSERT(ip->i_df.if_broot != NULL); |
374 | vecp->i_addr = (xfs_caddr_t)ip->i_df.if_broot; | 363 | vecp->i_addr = ip->i_df.if_broot; |
375 | vecp->i_len = ip->i_df.if_broot_bytes; | 364 | vecp->i_len = ip->i_df.if_broot_bytes; |
376 | vecp->i_type = XLOG_REG_TYPE_IBROOT; | 365 | vecp->i_type = XLOG_REG_TYPE_IBROOT; |
377 | vecp++; | 366 | vecp++; |
@@ -389,7 +378,7 @@ xfs_inode_item_format( | |||
389 | ASSERT(ip->i_df.if_u1.if_data != NULL); | 378 | ASSERT(ip->i_df.if_u1.if_data != NULL); |
390 | ASSERT(ip->i_d.di_size > 0); | 379 | ASSERT(ip->i_d.di_size > 0); |
391 | 380 | ||
392 | vecp->i_addr = (xfs_caddr_t)ip->i_df.if_u1.if_data; | 381 | vecp->i_addr = ip->i_df.if_u1.if_data; |
393 | /* | 382 | /* |
394 | * Round i_bytes up to a word boundary. | 383 | * Round i_bytes up to a word boundary. |
395 | * The underlying memory is guaranteed to | 384 | * The underlying memory is guaranteed to |
@@ -437,7 +426,7 @@ xfs_inode_item_format( | |||
437 | * Assert that no attribute-related log flags are set. | 426 | * Assert that no attribute-related log flags are set. |
438 | */ | 427 | */ |
439 | if (!XFS_IFORK_Q(ip)) { | 428 | if (!XFS_IFORK_Q(ip)) { |
440 | ASSERT(nvecs == iip->ili_item.li_desc->lid_size); | 429 | ASSERT(nvecs == lip->li_desc->lid_size); |
441 | iip->ili_format.ilf_size = nvecs; | 430 | iip->ili_format.ilf_size = nvecs; |
442 | ASSERT(!(iip->ili_format.ilf_fields & | 431 | ASSERT(!(iip->ili_format.ilf_fields & |
443 | (XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT))); | 432 | (XFS_ILOG_ADATA | XFS_ILOG_ABROOT | XFS_ILOG_AEXT))); |
@@ -449,21 +438,21 @@ xfs_inode_item_format( | |||
449 | ASSERT(!(iip->ili_format.ilf_fields & | 438 | ASSERT(!(iip->ili_format.ilf_fields & |
450 | (XFS_ILOG_ADATA | XFS_ILOG_ABROOT))); | 439 | (XFS_ILOG_ADATA | XFS_ILOG_ABROOT))); |
451 | if (iip->ili_format.ilf_fields & XFS_ILOG_AEXT) { | 440 | if (iip->ili_format.ilf_fields & XFS_ILOG_AEXT) { |
452 | ASSERT(ip->i_afp->if_bytes > 0); | ||
453 | ASSERT(ip->i_afp->if_u1.if_extents != NULL); | ||
454 | ASSERT(ip->i_d.di_anextents > 0); | ||
455 | #ifdef DEBUG | 441 | #ifdef DEBUG |
456 | nrecs = ip->i_afp->if_bytes / | 442 | int nrecs = ip->i_afp->if_bytes / |
457 | (uint)sizeof(xfs_bmbt_rec_t); | 443 | (uint)sizeof(xfs_bmbt_rec_t); |
458 | #endif | ||
459 | ASSERT(nrecs > 0); | 444 | ASSERT(nrecs > 0); |
460 | ASSERT(nrecs == ip->i_d.di_anextents); | 445 | ASSERT(nrecs == ip->i_d.di_anextents); |
446 | ASSERT(ip->i_afp->if_bytes > 0); | ||
447 | ASSERT(ip->i_afp->if_u1.if_extents != NULL); | ||
448 | ASSERT(ip->i_d.di_anextents > 0); | ||
449 | #endif | ||
461 | #ifdef XFS_NATIVE_HOST | 450 | #ifdef XFS_NATIVE_HOST |
462 | /* | 451 | /* |
463 | * There are not delayed allocation extents | 452 | * There are not delayed allocation extents |
464 | * for attributes, so just point at the array. | 453 | * for attributes, so just point at the array. |
465 | */ | 454 | */ |
466 | vecp->i_addr = (char *)(ip->i_afp->if_u1.if_extents); | 455 | vecp->i_addr = ip->i_afp->if_u1.if_extents; |
467 | vecp->i_len = ip->i_afp->if_bytes; | 456 | vecp->i_len = ip->i_afp->if_bytes; |
468 | #else | 457 | #else |
469 | ASSERT(iip->ili_aextents_buf == NULL); | 458 | ASSERT(iip->ili_aextents_buf == NULL); |
@@ -473,7 +462,7 @@ xfs_inode_item_format( | |||
473 | ext_buffer = kmem_alloc(ip->i_afp->if_bytes, | 462 | ext_buffer = kmem_alloc(ip->i_afp->if_bytes, |
474 | KM_SLEEP); | 463 | KM_SLEEP); |
475 | iip->ili_aextents_buf = ext_buffer; | 464 | iip->ili_aextents_buf = ext_buffer; |
476 | vecp->i_addr = (xfs_caddr_t)ext_buffer; | 465 | vecp->i_addr = ext_buffer; |
477 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, | 466 | vecp->i_len = xfs_iextents_copy(ip, ext_buffer, |
478 | XFS_ATTR_FORK); | 467 | XFS_ATTR_FORK); |
479 | #endif | 468 | #endif |
@@ -490,7 +479,7 @@ xfs_inode_item_format( | |||
490 | if (iip->ili_format.ilf_fields & XFS_ILOG_ABROOT) { | 479 | if (iip->ili_format.ilf_fields & XFS_ILOG_ABROOT) { |
491 | ASSERT(ip->i_afp->if_broot_bytes > 0); | 480 | ASSERT(ip->i_afp->if_broot_bytes > 0); |
492 | ASSERT(ip->i_afp->if_broot != NULL); | 481 | ASSERT(ip->i_afp->if_broot != NULL); |
493 | vecp->i_addr = (xfs_caddr_t)ip->i_afp->if_broot; | 482 | vecp->i_addr = ip->i_afp->if_broot; |
494 | vecp->i_len = ip->i_afp->if_broot_bytes; | 483 | vecp->i_len = ip->i_afp->if_broot_bytes; |
495 | vecp->i_type = XLOG_REG_TYPE_IATTR_BROOT; | 484 | vecp->i_type = XLOG_REG_TYPE_IATTR_BROOT; |
496 | vecp++; | 485 | vecp++; |
@@ -506,7 +495,7 @@ xfs_inode_item_format( | |||
506 | ASSERT(ip->i_afp->if_bytes > 0); | 495 | ASSERT(ip->i_afp->if_bytes > 0); |
507 | ASSERT(ip->i_afp->if_u1.if_data != NULL); | 496 | ASSERT(ip->i_afp->if_u1.if_data != NULL); |
508 | 497 | ||
509 | vecp->i_addr = (xfs_caddr_t)ip->i_afp->if_u1.if_data; | 498 | vecp->i_addr = ip->i_afp->if_u1.if_data; |
510 | /* | 499 | /* |
511 | * Round i_bytes up to a word boundary. | 500 | * Round i_bytes up to a word boundary. |
512 | * The underlying memory is guaranteed to | 501 | * The underlying memory is guaranteed to |
@@ -528,7 +517,7 @@ xfs_inode_item_format( | |||
528 | break; | 517 | break; |
529 | } | 518 | } |
530 | 519 | ||
531 | ASSERT(nvecs == iip->ili_item.li_desc->lid_size); | 520 | ASSERT(nvecs == lip->li_desc->lid_size); |
532 | iip->ili_format.ilf_size = nvecs; | 521 | iip->ili_format.ilf_size = nvecs; |
533 | } | 522 | } |
534 | 523 | ||
@@ -539,12 +528,14 @@ xfs_inode_item_format( | |||
539 | */ | 528 | */ |
540 | STATIC void | 529 | STATIC void |
541 | xfs_inode_item_pin( | 530 | xfs_inode_item_pin( |
542 | xfs_inode_log_item_t *iip) | 531 | struct xfs_log_item *lip) |
543 | { | 532 | { |
544 | ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL)); | 533 | struct xfs_inode *ip = INODE_ITEM(lip)->ili_inode; |
534 | |||
535 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
545 | 536 | ||
546 | trace_xfs_inode_pin(iip->ili_inode, _RET_IP_); | 537 | trace_xfs_inode_pin(ip, _RET_IP_); |
547 | atomic_inc(&iip->ili_inode->i_pincount); | 538 | atomic_inc(&ip->i_pincount); |
548 | } | 539 | } |
549 | 540 | ||
550 | 541 | ||
@@ -554,12 +545,12 @@ xfs_inode_item_pin( | |||
554 | * | 545 | * |
555 | * Also wake up anyone in xfs_iunpin_wait() if the count goes to 0. | 546 | * Also wake up anyone in xfs_iunpin_wait() if the count goes to 0. |
556 | */ | 547 | */ |
557 | /* ARGSUSED */ | ||
558 | STATIC void | 548 | STATIC void |
559 | xfs_inode_item_unpin( | 549 | xfs_inode_item_unpin( |
560 | xfs_inode_log_item_t *iip) | 550 | struct xfs_log_item *lip, |
551 | int remove) | ||
561 | { | 552 | { |
562 | struct xfs_inode *ip = iip->ili_inode; | 553 | struct xfs_inode *ip = INODE_ITEM(lip)->ili_inode; |
563 | 554 | ||
564 | trace_xfs_inode_unpin(ip, _RET_IP_); | 555 | trace_xfs_inode_unpin(ip, _RET_IP_); |
565 | ASSERT(atomic_read(&ip->i_pincount) > 0); | 556 | ASSERT(atomic_read(&ip->i_pincount) > 0); |
@@ -567,15 +558,6 @@ xfs_inode_item_unpin( | |||
567 | wake_up(&ip->i_ipin_wait); | 558 | wake_up(&ip->i_ipin_wait); |
568 | } | 559 | } |
569 | 560 | ||
570 | /* ARGSUSED */ | ||
571 | STATIC void | ||
572 | xfs_inode_item_unpin_remove( | ||
573 | xfs_inode_log_item_t *iip, | ||
574 | xfs_trans_t *tp) | ||
575 | { | ||
576 | xfs_inode_item_unpin(iip); | ||
577 | } | ||
578 | |||
579 | /* | 561 | /* |
580 | * This is called to attempt to lock the inode associated with this | 562 | * This is called to attempt to lock the inode associated with this |
581 | * inode log item, in preparation for the push routine which does the actual | 563 | * inode log item, in preparation for the push routine which does the actual |
@@ -591,19 +573,16 @@ xfs_inode_item_unpin_remove( | |||
591 | */ | 573 | */ |
592 | STATIC uint | 574 | STATIC uint |
593 | xfs_inode_item_trylock( | 575 | xfs_inode_item_trylock( |
594 | xfs_inode_log_item_t *iip) | 576 | struct xfs_log_item *lip) |
595 | { | 577 | { |
596 | register xfs_inode_t *ip; | 578 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); |
597 | 579 | struct xfs_inode *ip = iip->ili_inode; | |
598 | ip = iip->ili_inode; | ||
599 | 580 | ||
600 | if (xfs_ipincount(ip) > 0) { | 581 | if (xfs_ipincount(ip) > 0) |
601 | return XFS_ITEM_PINNED; | 582 | return XFS_ITEM_PINNED; |
602 | } | ||
603 | 583 | ||
604 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) { | 584 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) |
605 | return XFS_ITEM_LOCKED; | 585 | return XFS_ITEM_LOCKED; |
606 | } | ||
607 | 586 | ||
608 | if (!xfs_iflock_nowait(ip)) { | 587 | if (!xfs_iflock_nowait(ip)) { |
609 | /* | 588 | /* |
@@ -629,7 +608,7 @@ xfs_inode_item_trylock( | |||
629 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | 608 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
630 | ASSERT(iip->ili_format.ilf_fields != 0); | 609 | ASSERT(iip->ili_format.ilf_fields != 0); |
631 | ASSERT(iip->ili_logged == 0); | 610 | ASSERT(iip->ili_logged == 0); |
632 | ASSERT(iip->ili_item.li_flags & XFS_LI_IN_AIL); | 611 | ASSERT(lip->li_flags & XFS_LI_IN_AIL); |
633 | } | 612 | } |
634 | #endif | 613 | #endif |
635 | return XFS_ITEM_SUCCESS; | 614 | return XFS_ITEM_SUCCESS; |
@@ -643,26 +622,18 @@ xfs_inode_item_trylock( | |||
643 | */ | 622 | */ |
644 | STATIC void | 623 | STATIC void |
645 | xfs_inode_item_unlock( | 624 | xfs_inode_item_unlock( |
646 | xfs_inode_log_item_t *iip) | 625 | struct xfs_log_item *lip) |
647 | { | 626 | { |
648 | uint hold; | 627 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); |
649 | uint iolocked; | 628 | struct xfs_inode *ip = iip->ili_inode; |
650 | uint lock_flags; | 629 | unsigned short lock_flags; |
651 | xfs_inode_t *ip; | ||
652 | 630 | ||
653 | ASSERT(iip != NULL); | ||
654 | ASSERT(iip->ili_inode->i_itemp != NULL); | 631 | ASSERT(iip->ili_inode->i_itemp != NULL); |
655 | ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL)); | 632 | ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL)); |
656 | ASSERT((!(iip->ili_inode->i_itemp->ili_flags & | 633 | |
657 | XFS_ILI_IOLOCKED_EXCL)) || | ||
658 | xfs_isilocked(iip->ili_inode, XFS_IOLOCK_EXCL)); | ||
659 | ASSERT((!(iip->ili_inode->i_itemp->ili_flags & | ||
660 | XFS_ILI_IOLOCKED_SHARED)) || | ||
661 | xfs_isilocked(iip->ili_inode, XFS_IOLOCK_SHARED)); | ||
662 | /* | 634 | /* |
663 | * Clear the transaction pointer in the inode. | 635 | * Clear the transaction pointer in the inode. |
664 | */ | 636 | */ |
665 | ip = iip->ili_inode; | ||
666 | ip->i_transp = NULL; | 637 | ip->i_transp = NULL; |
667 | 638 | ||
668 | /* | 639 | /* |
@@ -686,34 +657,11 @@ xfs_inode_item_unlock( | |||
686 | iip->ili_aextents_buf = NULL; | 657 | iip->ili_aextents_buf = NULL; |
687 | } | 658 | } |
688 | 659 | ||
689 | /* | 660 | lock_flags = iip->ili_lock_flags; |
690 | * Figure out if we should unlock the inode or not. | 661 | iip->ili_lock_flags = 0; |
691 | */ | 662 | if (lock_flags) { |
692 | hold = iip->ili_flags & XFS_ILI_HOLD; | 663 | xfs_iunlock(iip->ili_inode, lock_flags); |
693 | 664 | IRELE(iip->ili_inode); | |
694 | /* | ||
695 | * Before clearing out the flags, remember whether we | ||
696 | * are holding the inode's IO lock. | ||
697 | */ | ||
698 | iolocked = iip->ili_flags & XFS_ILI_IOLOCKED_ANY; | ||
699 | |||
700 | /* | ||
701 | * Clear out the fields of the inode log item particular | ||
702 | * to the current transaction. | ||
703 | */ | ||
704 | iip->ili_flags = 0; | ||
705 | |||
706 | /* | ||
707 | * Unlock the inode if XFS_ILI_HOLD was not set. | ||
708 | */ | ||
709 | if (!hold) { | ||
710 | lock_flags = XFS_ILOCK_EXCL; | ||
711 | if (iolocked & XFS_ILI_IOLOCKED_EXCL) { | ||
712 | lock_flags |= XFS_IOLOCK_EXCL; | ||
713 | } else if (iolocked & XFS_ILI_IOLOCKED_SHARED) { | ||
714 | lock_flags |= XFS_IOLOCK_SHARED; | ||
715 | } | ||
716 | xfs_iput(iip->ili_inode, lock_flags); | ||
717 | } | 665 | } |
718 | } | 666 | } |
719 | 667 | ||
@@ -725,13 +673,12 @@ xfs_inode_item_unlock( | |||
725 | * is the only one that matters. Therefore, simply return the | 673 | * is the only one that matters. Therefore, simply return the |
726 | * given lsn. | 674 | * given lsn. |
727 | */ | 675 | */ |
728 | /*ARGSUSED*/ | ||
729 | STATIC xfs_lsn_t | 676 | STATIC xfs_lsn_t |
730 | xfs_inode_item_committed( | 677 | xfs_inode_item_committed( |
731 | xfs_inode_log_item_t *iip, | 678 | struct xfs_log_item *lip, |
732 | xfs_lsn_t lsn) | 679 | xfs_lsn_t lsn) |
733 | { | 680 | { |
734 | return (lsn); | 681 | return lsn; |
735 | } | 682 | } |
736 | 683 | ||
737 | /* | 684 | /* |
@@ -743,13 +690,12 @@ xfs_inode_item_committed( | |||
743 | */ | 690 | */ |
744 | STATIC void | 691 | STATIC void |
745 | xfs_inode_item_pushbuf( | 692 | xfs_inode_item_pushbuf( |
746 | xfs_inode_log_item_t *iip) | 693 | struct xfs_log_item *lip) |
747 | { | 694 | { |
748 | xfs_inode_t *ip; | 695 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); |
749 | xfs_mount_t *mp; | 696 | struct xfs_inode *ip = iip->ili_inode; |
750 | xfs_buf_t *bp; | 697 | struct xfs_buf *bp; |
751 | 698 | ||
752 | ip = iip->ili_inode; | ||
753 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED)); | 699 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED)); |
754 | 700 | ||
755 | /* | 701 | /* |
@@ -757,14 +703,13 @@ xfs_inode_item_pushbuf( | |||
757 | * inode was taken off the AIL. So, just get out. | 703 | * inode was taken off the AIL. So, just get out. |
758 | */ | 704 | */ |
759 | if (completion_done(&ip->i_flush) || | 705 | if (completion_done(&ip->i_flush) || |
760 | ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) { | 706 | !(lip->li_flags & XFS_LI_IN_AIL)) { |
761 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 707 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
762 | return; | 708 | return; |
763 | } | 709 | } |
764 | 710 | ||
765 | mp = ip->i_mount; | 711 | bp = xfs_incore(ip->i_mount->m_ddev_targp, iip->ili_format.ilf_blkno, |
766 | bp = xfs_incore(mp->m_ddev_targp, iip->ili_format.ilf_blkno, | 712 | iip->ili_format.ilf_len, XBF_TRYLOCK); |
767 | iip->ili_format.ilf_len, XBF_TRYLOCK); | ||
768 | 713 | ||
769 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 714 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
770 | if (!bp) | 715 | if (!bp) |
@@ -772,10 +717,8 @@ xfs_inode_item_pushbuf( | |||
772 | if (XFS_BUF_ISDELAYWRITE(bp)) | 717 | if (XFS_BUF_ISDELAYWRITE(bp)) |
773 | xfs_buf_delwri_promote(bp); | 718 | xfs_buf_delwri_promote(bp); |
774 | xfs_buf_relse(bp); | 719 | xfs_buf_relse(bp); |
775 | return; | ||
776 | } | 720 | } |
777 | 721 | ||
778 | |||
779 | /* | 722 | /* |
780 | * This is called to asynchronously write the inode associated with this | 723 | * This is called to asynchronously write the inode associated with this |
781 | * inode log item out to disk. The inode will already have been locked by | 724 | * inode log item out to disk. The inode will already have been locked by |
@@ -783,14 +726,14 @@ xfs_inode_item_pushbuf( | |||
783 | */ | 726 | */ |
784 | STATIC void | 727 | STATIC void |
785 | xfs_inode_item_push( | 728 | xfs_inode_item_push( |
786 | xfs_inode_log_item_t *iip) | 729 | struct xfs_log_item *lip) |
787 | { | 730 | { |
788 | xfs_inode_t *ip; | 731 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); |
789 | 732 | struct xfs_inode *ip = iip->ili_inode; | |
790 | ip = iip->ili_inode; | ||
791 | 733 | ||
792 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED)); | 734 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED)); |
793 | ASSERT(!completion_done(&ip->i_flush)); | 735 | ASSERT(!completion_done(&ip->i_flush)); |
736 | |||
794 | /* | 737 | /* |
795 | * Since we were able to lock the inode's flush lock and | 738 | * Since we were able to lock the inode's flush lock and |
796 | * we found it on the AIL, the inode must be dirty. This | 739 | * we found it on the AIL, the inode must be dirty. This |
@@ -813,43 +756,34 @@ xfs_inode_item_push( | |||
813 | */ | 756 | */ |
814 | (void) xfs_iflush(ip, 0); | 757 | (void) xfs_iflush(ip, 0); |
815 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 758 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
816 | |||
817 | return; | ||
818 | } | 759 | } |
819 | 760 | ||
820 | /* | 761 | /* |
821 | * XXX rcc - this one really has to do something. Probably needs | 762 | * XXX rcc - this one really has to do something. Probably needs |
822 | * to stamp in a new field in the incore inode. | 763 | * to stamp in a new field in the incore inode. |
823 | */ | 764 | */ |
824 | /* ARGSUSED */ | ||
825 | STATIC void | 765 | STATIC void |
826 | xfs_inode_item_committing( | 766 | xfs_inode_item_committing( |
827 | xfs_inode_log_item_t *iip, | 767 | struct xfs_log_item *lip, |
828 | xfs_lsn_t lsn) | 768 | xfs_lsn_t lsn) |
829 | { | 769 | { |
830 | iip->ili_last_lsn = lsn; | 770 | INODE_ITEM(lip)->ili_last_lsn = lsn; |
831 | return; | ||
832 | } | 771 | } |
833 | 772 | ||
834 | /* | 773 | /* |
835 | * This is the ops vector shared by all buf log items. | 774 | * This is the ops vector shared by all buf log items. |
836 | */ | 775 | */ |
837 | static struct xfs_item_ops xfs_inode_item_ops = { | 776 | static struct xfs_item_ops xfs_inode_item_ops = { |
838 | .iop_size = (uint(*)(xfs_log_item_t*))xfs_inode_item_size, | 777 | .iop_size = xfs_inode_item_size, |
839 | .iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*)) | 778 | .iop_format = xfs_inode_item_format, |
840 | xfs_inode_item_format, | 779 | .iop_pin = xfs_inode_item_pin, |
841 | .iop_pin = (void(*)(xfs_log_item_t*))xfs_inode_item_pin, | 780 | .iop_unpin = xfs_inode_item_unpin, |
842 | .iop_unpin = (void(*)(xfs_log_item_t*))xfs_inode_item_unpin, | 781 | .iop_trylock = xfs_inode_item_trylock, |
843 | .iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t*)) | 782 | .iop_unlock = xfs_inode_item_unlock, |
844 | xfs_inode_item_unpin_remove, | 783 | .iop_committed = xfs_inode_item_committed, |
845 | .iop_trylock = (uint(*)(xfs_log_item_t*))xfs_inode_item_trylock, | 784 | .iop_push = xfs_inode_item_push, |
846 | .iop_unlock = (void(*)(xfs_log_item_t*))xfs_inode_item_unlock, | 785 | .iop_pushbuf = xfs_inode_item_pushbuf, |
847 | .iop_committed = (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t)) | 786 | .iop_committing = xfs_inode_item_committing |
848 | xfs_inode_item_committed, | ||
849 | .iop_push = (void(*)(xfs_log_item_t*))xfs_inode_item_push, | ||
850 | .iop_pushbuf = (void(*)(xfs_log_item_t*))xfs_inode_item_pushbuf, | ||
851 | .iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t)) | ||
852 | xfs_inode_item_committing | ||
853 | }; | 787 | }; |
854 | 788 | ||
855 | 789 | ||
@@ -858,10 +792,10 @@ static struct xfs_item_ops xfs_inode_item_ops = { | |||
858 | */ | 792 | */ |
859 | void | 793 | void |
860 | xfs_inode_item_init( | 794 | xfs_inode_item_init( |
861 | xfs_inode_t *ip, | 795 | struct xfs_inode *ip, |
862 | xfs_mount_t *mp) | 796 | struct xfs_mount *mp) |
863 | { | 797 | { |
864 | xfs_inode_log_item_t *iip; | 798 | struct xfs_inode_log_item *iip; |
865 | 799 | ||
866 | ASSERT(ip->i_itemp == NULL); | 800 | ASSERT(ip->i_itemp == NULL); |
867 | iip = ip->i_itemp = kmem_zone_zalloc(xfs_ili_zone, KM_SLEEP); | 801 | iip = ip->i_itemp = kmem_zone_zalloc(xfs_ili_zone, KM_SLEEP); |
@@ -899,14 +833,14 @@ xfs_inode_item_destroy( | |||
899 | * from the AIL if it has not been re-logged, and unlocking the inode's | 833 | * from the AIL if it has not been re-logged, and unlocking the inode's |
900 | * flush lock. | 834 | * flush lock. |
901 | */ | 835 | */ |
902 | /*ARGSUSED*/ | ||
903 | void | 836 | void |
904 | xfs_iflush_done( | 837 | xfs_iflush_done( |
905 | xfs_buf_t *bp, | 838 | struct xfs_buf *bp, |
906 | xfs_inode_log_item_t *iip) | 839 | struct xfs_log_item *lip) |
907 | { | 840 | { |
841 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); | ||
908 | xfs_inode_t *ip = iip->ili_inode; | 842 | xfs_inode_t *ip = iip->ili_inode; |
909 | struct xfs_ail *ailp = iip->ili_item.li_ailp; | 843 | struct xfs_ail *ailp = lip->li_ailp; |
910 | 844 | ||
911 | /* | 845 | /* |
912 | * We only want to pull the item from the AIL if it is | 846 | * We only want to pull the item from the AIL if it is |
@@ -917,12 +851,11 @@ xfs_iflush_done( | |||
917 | * the lock since it's cheaper, and then we recheck while | 851 | * the lock since it's cheaper, and then we recheck while |
918 | * holding the lock before removing the inode from the AIL. | 852 | * holding the lock before removing the inode from the AIL. |
919 | */ | 853 | */ |
920 | if (iip->ili_logged && | 854 | if (iip->ili_logged && lip->li_lsn == iip->ili_flush_lsn) { |
921 | (iip->ili_item.li_lsn == iip->ili_flush_lsn)) { | ||
922 | spin_lock(&ailp->xa_lock); | 855 | spin_lock(&ailp->xa_lock); |
923 | if (iip->ili_item.li_lsn == iip->ili_flush_lsn) { | 856 | if (lip->li_lsn == iip->ili_flush_lsn) { |
924 | /* xfs_trans_ail_delete() drops the AIL lock. */ | 857 | /* xfs_trans_ail_delete() drops the AIL lock. */ |
925 | xfs_trans_ail_delete(ailp, (xfs_log_item_t*)iip); | 858 | xfs_trans_ail_delete(ailp, lip); |
926 | } else { | 859 | } else { |
927 | spin_unlock(&ailp->xa_lock); | 860 | spin_unlock(&ailp->xa_lock); |
928 | } | 861 | } |
@@ -940,8 +873,6 @@ xfs_iflush_done( | |||
940 | * Release the inode's flush lock since we're done with it. | 873 | * Release the inode's flush lock since we're done with it. |
941 | */ | 874 | */ |
942 | xfs_ifunlock(ip); | 875 | xfs_ifunlock(ip); |
943 | |||
944 | return; | ||
945 | } | 876 | } |
946 | 877 | ||
947 | /* | 878 | /* |
@@ -957,10 +888,8 @@ xfs_iflush_abort( | |||
957 | xfs_inode_t *ip) | 888 | xfs_inode_t *ip) |
958 | { | 889 | { |
959 | xfs_inode_log_item_t *iip = ip->i_itemp; | 890 | xfs_inode_log_item_t *iip = ip->i_itemp; |
960 | xfs_mount_t *mp; | ||
961 | 891 | ||
962 | iip = ip->i_itemp; | 892 | iip = ip->i_itemp; |
963 | mp = ip->i_mount; | ||
964 | if (iip) { | 893 | if (iip) { |
965 | struct xfs_ail *ailp = iip->ili_item.li_ailp; | 894 | struct xfs_ail *ailp = iip->ili_item.li_ailp; |
966 | if (iip->ili_item.li_flags & XFS_LI_IN_AIL) { | 895 | if (iip->ili_item.li_flags & XFS_LI_IN_AIL) { |
@@ -991,10 +920,10 @@ xfs_iflush_abort( | |||
991 | 920 | ||
992 | void | 921 | void |
993 | xfs_istale_done( | 922 | xfs_istale_done( |
994 | xfs_buf_t *bp, | 923 | struct xfs_buf *bp, |
995 | xfs_inode_log_item_t *iip) | 924 | struct xfs_log_item *lip) |
996 | { | 925 | { |
997 | xfs_iflush_abort(iip->ili_inode); | 926 | xfs_iflush_abort(INODE_ITEM(lip)->ili_inode); |
998 | } | 927 | } |
999 | 928 | ||
1000 | /* | 929 | /* |
@@ -1007,9 +936,8 @@ xfs_inode_item_format_convert( | |||
1007 | xfs_inode_log_format_t *in_f) | 936 | xfs_inode_log_format_t *in_f) |
1008 | { | 937 | { |
1009 | if (buf->i_len == sizeof(xfs_inode_log_format_32_t)) { | 938 | if (buf->i_len == sizeof(xfs_inode_log_format_32_t)) { |
1010 | xfs_inode_log_format_32_t *in_f32; | 939 | xfs_inode_log_format_32_t *in_f32 = buf->i_addr; |
1011 | 940 | ||
1012 | in_f32 = (xfs_inode_log_format_32_t *)buf->i_addr; | ||
1013 | in_f->ilf_type = in_f32->ilf_type; | 941 | in_f->ilf_type = in_f32->ilf_type; |
1014 | in_f->ilf_size = in_f32->ilf_size; | 942 | in_f->ilf_size = in_f32->ilf_size; |
1015 | in_f->ilf_fields = in_f32->ilf_fields; | 943 | in_f->ilf_fields = in_f32->ilf_fields; |
@@ -1025,9 +953,8 @@ xfs_inode_item_format_convert( | |||
1025 | in_f->ilf_boffset = in_f32->ilf_boffset; | 953 | in_f->ilf_boffset = in_f32->ilf_boffset; |
1026 | return 0; | 954 | return 0; |
1027 | } else if (buf->i_len == sizeof(xfs_inode_log_format_64_t)){ | 955 | } else if (buf->i_len == sizeof(xfs_inode_log_format_64_t)){ |
1028 | xfs_inode_log_format_64_t *in_f64; | 956 | xfs_inode_log_format_64_t *in_f64 = buf->i_addr; |
1029 | 957 | ||
1030 | in_f64 = (xfs_inode_log_format_64_t *)buf->i_addr; | ||
1031 | in_f->ilf_type = in_f64->ilf_type; | 958 | in_f->ilf_type = in_f64->ilf_type; |
1032 | in_f->ilf_size = in_f64->ilf_size; | 959 | in_f->ilf_size = in_f64->ilf_size; |
1033 | in_f->ilf_fields = in_f64->ilf_fields; | 960 | in_f->ilf_fields = in_f64->ilf_fields; |
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h index 9a467958ecdd..d3dee61e6d91 100644 --- a/fs/xfs/xfs_inode_item.h +++ b/fs/xfs/xfs_inode_item.h | |||
@@ -103,12 +103,6 @@ typedef struct xfs_inode_log_format_64 { | |||
103 | XFS_ILOG_ADATA | XFS_ILOG_AEXT | \ | 103 | XFS_ILOG_ADATA | XFS_ILOG_AEXT | \ |
104 | XFS_ILOG_ABROOT) | 104 | XFS_ILOG_ABROOT) |
105 | 105 | ||
106 | #define XFS_ILI_HOLD 0x1 | ||
107 | #define XFS_ILI_IOLOCKED_EXCL 0x2 | ||
108 | #define XFS_ILI_IOLOCKED_SHARED 0x4 | ||
109 | |||
110 | #define XFS_ILI_IOLOCKED_ANY (XFS_ILI_IOLOCKED_EXCL | XFS_ILI_IOLOCKED_SHARED) | ||
111 | |||
112 | static inline int xfs_ilog_fbroot(int w) | 106 | static inline int xfs_ilog_fbroot(int w) |
113 | { | 107 | { |
114 | return (w == XFS_DATA_FORK ? XFS_ILOG_DBROOT : XFS_ILOG_ABROOT); | 108 | return (w == XFS_DATA_FORK ? XFS_ILOG_DBROOT : XFS_ILOG_ABROOT); |
@@ -137,7 +131,7 @@ typedef struct xfs_inode_log_item { | |||
137 | struct xfs_inode *ili_inode; /* inode ptr */ | 131 | struct xfs_inode *ili_inode; /* inode ptr */ |
138 | xfs_lsn_t ili_flush_lsn; /* lsn at last flush */ | 132 | xfs_lsn_t ili_flush_lsn; /* lsn at last flush */ |
139 | xfs_lsn_t ili_last_lsn; /* lsn at last transaction */ | 133 | xfs_lsn_t ili_last_lsn; /* lsn at last transaction */ |
140 | unsigned short ili_flags; /* misc flags */ | 134 | unsigned short ili_lock_flags; /* lock flags */ |
141 | unsigned short ili_logged; /* flushed logged data */ | 135 | unsigned short ili_logged; /* flushed logged data */ |
142 | unsigned int ili_last_fields; /* fields when flushed */ | 136 | unsigned int ili_last_fields; /* fields when flushed */ |
143 | struct xfs_bmbt_rec *ili_extents_buf; /* array of logged | 137 | struct xfs_bmbt_rec *ili_extents_buf; /* array of logged |
@@ -161,8 +155,8 @@ static inline int xfs_inode_clean(xfs_inode_t *ip) | |||
161 | 155 | ||
162 | extern void xfs_inode_item_init(struct xfs_inode *, struct xfs_mount *); | 156 | extern void xfs_inode_item_init(struct xfs_inode *, struct xfs_mount *); |
163 | extern void xfs_inode_item_destroy(struct xfs_inode *); | 157 | extern void xfs_inode_item_destroy(struct xfs_inode *); |
164 | extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *); | 158 | extern void xfs_iflush_done(struct xfs_buf *, struct xfs_log_item *); |
165 | extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *); | 159 | extern void xfs_istale_done(struct xfs_buf *, struct xfs_log_item *); |
166 | extern void xfs_iflush_abort(struct xfs_inode *); | 160 | extern void xfs_iflush_abort(struct xfs_inode *); |
167 | extern int xfs_inode_item_format_convert(xfs_log_iovec_t *, | 161 | extern int xfs_inode_item_format_convert(xfs_log_iovec_t *, |
168 | xfs_inode_log_format_t *); | 162 | xfs_inode_log_format_t *); |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index ef14943829da..20576146369f 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -23,19 +23,14 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | ||
27 | #include "xfs_alloc.h" | 26 | #include "xfs_alloc.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_quota.h" | 27 | #include "xfs_quota.h" |
30 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 30 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 31 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
37 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
38 | #include "xfs_ialloc.h" | ||
39 | #include "xfs_btree.h" | 34 | #include "xfs_btree.h" |
40 | #include "xfs_bmap.h" | 35 | #include "xfs_bmap.h" |
41 | #include "xfs_rtalloc.h" | 36 | #include "xfs_rtalloc.h" |
@@ -123,7 +118,7 @@ xfs_iomap( | |||
123 | error = xfs_bmapi(NULL, ip, offset_fsb, | 118 | error = xfs_bmapi(NULL, ip, offset_fsb, |
124 | (xfs_filblks_t)(end_fsb - offset_fsb), | 119 | (xfs_filblks_t)(end_fsb - offset_fsb), |
125 | bmapi_flags, NULL, 0, imap, | 120 | bmapi_flags, NULL, 0, imap, |
126 | nimaps, NULL, NULL); | 121 | nimaps, NULL); |
127 | 122 | ||
128 | if (error) | 123 | if (error) |
129 | goto out; | 124 | goto out; |
@@ -138,7 +133,7 @@ xfs_iomap( | |||
138 | break; | 133 | break; |
139 | } | 134 | } |
140 | 135 | ||
141 | if (flags & (BMAPI_DIRECT|BMAPI_MMAP)) { | 136 | if (flags & BMAPI_DIRECT) { |
142 | error = xfs_iomap_write_direct(ip, offset, count, flags, | 137 | error = xfs_iomap_write_direct(ip, offset, count, flags, |
143 | imap, nimaps); | 138 | imap, nimaps); |
144 | } else { | 139 | } else { |
@@ -247,7 +242,7 @@ xfs_iomap_write_direct( | |||
247 | xfs_off_t offset, | 242 | xfs_off_t offset, |
248 | size_t count, | 243 | size_t count, |
249 | int flags, | 244 | int flags, |
250 | xfs_bmbt_irec_t *ret_imap, | 245 | xfs_bmbt_irec_t *imap, |
251 | int *nmaps) | 246 | int *nmaps) |
252 | { | 247 | { |
253 | xfs_mount_t *mp = ip->i_mount; | 248 | xfs_mount_t *mp = ip->i_mount; |
@@ -261,7 +256,6 @@ xfs_iomap_write_direct( | |||
261 | int quota_flag; | 256 | int quota_flag; |
262 | int rt; | 257 | int rt; |
263 | xfs_trans_t *tp; | 258 | xfs_trans_t *tp; |
264 | xfs_bmbt_irec_t imap; | ||
265 | xfs_bmap_free_t free_list; | 259 | xfs_bmap_free_t free_list; |
266 | uint qblocks, resblks, resrtextents; | 260 | uint qblocks, resblks, resrtextents; |
267 | int committed; | 261 | int committed; |
@@ -285,10 +279,10 @@ xfs_iomap_write_direct( | |||
285 | if (error) | 279 | if (error) |
286 | goto error_out; | 280 | goto error_out; |
287 | } else { | 281 | } else { |
288 | if (*nmaps && (ret_imap->br_startblock == HOLESTARTBLOCK)) | 282 | if (*nmaps && (imap->br_startblock == HOLESTARTBLOCK)) |
289 | last_fsb = MIN(last_fsb, (xfs_fileoff_t) | 283 | last_fsb = MIN(last_fsb, (xfs_fileoff_t) |
290 | ret_imap->br_blockcount + | 284 | imap->br_blockcount + |
291 | ret_imap->br_startoff); | 285 | imap->br_startoff); |
292 | } | 286 | } |
293 | count_fsb = last_fsb - offset_fsb; | 287 | count_fsb = last_fsb - offset_fsb; |
294 | ASSERT(count_fsb > 0); | 288 | ASSERT(count_fsb > 0); |
@@ -334,20 +328,22 @@ xfs_iomap_write_direct( | |||
334 | if (error) | 328 | if (error) |
335 | goto error1; | 329 | goto error1; |
336 | 330 | ||
337 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 331 | xfs_trans_ijoin(tp, ip); |
338 | xfs_trans_ihold(tp, ip); | ||
339 | 332 | ||
340 | bmapi_flag = XFS_BMAPI_WRITE; | 333 | bmapi_flag = XFS_BMAPI_WRITE; |
341 | if ((flags & BMAPI_DIRECT) && (offset < ip->i_size || extsz)) | 334 | if ((flags & BMAPI_DIRECT) && (offset < ip->i_size || extsz)) |
342 | bmapi_flag |= XFS_BMAPI_PREALLOC; | 335 | bmapi_flag |= XFS_BMAPI_PREALLOC; |
343 | 336 | ||
344 | /* | 337 | /* |
345 | * Issue the xfs_bmapi() call to allocate the blocks | 338 | * Issue the xfs_bmapi() call to allocate the blocks. |
339 | * | ||
340 | * From this point onwards we overwrite the imap pointer that the | ||
341 | * caller gave to us. | ||
346 | */ | 342 | */ |
347 | xfs_bmap_init(&free_list, &firstfsb); | 343 | xfs_bmap_init(&free_list, &firstfsb); |
348 | nimaps = 1; | 344 | nimaps = 1; |
349 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, bmapi_flag, | 345 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, bmapi_flag, |
350 | &firstfsb, 0, &imap, &nimaps, &free_list, NULL); | 346 | &firstfsb, 0, imap, &nimaps, &free_list); |
351 | if (error) | 347 | if (error) |
352 | goto error0; | 348 | goto error0; |
353 | 349 | ||
@@ -369,12 +365,11 @@ xfs_iomap_write_direct( | |||
369 | goto error_out; | 365 | goto error_out; |
370 | } | 366 | } |
371 | 367 | ||
372 | if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip))) { | 368 | if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) { |
373 | error = xfs_cmn_err_fsblock_zero(ip, &imap); | 369 | error = xfs_cmn_err_fsblock_zero(ip, imap); |
374 | goto error_out; | 370 | goto error_out; |
375 | } | 371 | } |
376 | 372 | ||
377 | *ret_imap = imap; | ||
378 | *nmaps = 1; | 373 | *nmaps = 1; |
379 | return 0; | 374 | return 0; |
380 | 375 | ||
@@ -425,7 +420,7 @@ xfs_iomap_eof_want_preallocate( | |||
425 | imaps = nimaps; | 420 | imaps = nimaps; |
426 | firstblock = NULLFSBLOCK; | 421 | firstblock = NULLFSBLOCK; |
427 | error = xfs_bmapi(NULL, ip, start_fsb, count_fsb, 0, | 422 | error = xfs_bmapi(NULL, ip, start_fsb, count_fsb, 0, |
428 | &firstblock, 0, imap, &imaps, NULL, NULL); | 423 | &firstblock, 0, imap, &imaps, NULL); |
429 | if (error) | 424 | if (error) |
430 | return error; | 425 | return error; |
431 | for (n = 0; n < imaps; n++) { | 426 | for (n = 0; n < imaps; n++) { |
@@ -500,7 +495,7 @@ retry: | |||
500 | (xfs_filblks_t)(last_fsb - offset_fsb), | 495 | (xfs_filblks_t)(last_fsb - offset_fsb), |
501 | XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | | 496 | XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | |
502 | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, | 497 | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, |
503 | &nimaps, NULL, NULL); | 498 | &nimaps, NULL); |
504 | if (error && (error != ENOSPC)) | 499 | if (error && (error != ENOSPC)) |
505 | return XFS_ERROR(error); | 500 | return XFS_ERROR(error); |
506 | 501 | ||
@@ -548,7 +543,7 @@ xfs_iomap_write_allocate( | |||
548 | xfs_inode_t *ip, | 543 | xfs_inode_t *ip, |
549 | xfs_off_t offset, | 544 | xfs_off_t offset, |
550 | size_t count, | 545 | size_t count, |
551 | xfs_bmbt_irec_t *map, | 546 | xfs_bmbt_irec_t *imap, |
552 | int *retmap) | 547 | int *retmap) |
553 | { | 548 | { |
554 | xfs_mount_t *mp = ip->i_mount; | 549 | xfs_mount_t *mp = ip->i_mount; |
@@ -557,7 +552,6 @@ xfs_iomap_write_allocate( | |||
557 | xfs_fsblock_t first_block; | 552 | xfs_fsblock_t first_block; |
558 | xfs_bmap_free_t free_list; | 553 | xfs_bmap_free_t free_list; |
559 | xfs_filblks_t count_fsb; | 554 | xfs_filblks_t count_fsb; |
560 | xfs_bmbt_irec_t imap; | ||
561 | xfs_trans_t *tp; | 555 | xfs_trans_t *tp; |
562 | int nimaps, committed; | 556 | int nimaps, committed; |
563 | int error = 0; | 557 | int error = 0; |
@@ -573,8 +567,8 @@ xfs_iomap_write_allocate( | |||
573 | return XFS_ERROR(error); | 567 | return XFS_ERROR(error); |
574 | 568 | ||
575 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 569 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
576 | count_fsb = map->br_blockcount; | 570 | count_fsb = imap->br_blockcount; |
577 | map_start_fsb = map->br_startoff; | 571 | map_start_fsb = imap->br_startoff; |
578 | 572 | ||
579 | XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb)); | 573 | XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb)); |
580 | 574 | ||
@@ -602,8 +596,7 @@ xfs_iomap_write_allocate( | |||
602 | return XFS_ERROR(error); | 596 | return XFS_ERROR(error); |
603 | } | 597 | } |
604 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 598 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
605 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 599 | xfs_trans_ijoin(tp, ip); |
606 | xfs_trans_ihold(tp, ip); | ||
607 | 600 | ||
608 | xfs_bmap_init(&free_list, &first_block); | 601 | xfs_bmap_init(&free_list, &first_block); |
609 | 602 | ||
@@ -654,10 +647,15 @@ xfs_iomap_write_allocate( | |||
654 | } | 647 | } |
655 | } | 648 | } |
656 | 649 | ||
657 | /* Go get the actual blocks */ | 650 | /* |
651 | * Go get the actual blocks. | ||
652 | * | ||
653 | * From this point onwards we overwrite the imap | ||
654 | * pointer that the caller gave to us. | ||
655 | */ | ||
658 | error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, | 656 | error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, |
659 | XFS_BMAPI_WRITE, &first_block, 1, | 657 | XFS_BMAPI_WRITE, &first_block, 1, |
660 | &imap, &nimaps, &free_list, NULL); | 658 | imap, &nimaps, &free_list); |
661 | if (error) | 659 | if (error) |
662 | goto trans_cancel; | 660 | goto trans_cancel; |
663 | 661 | ||
@@ -676,13 +674,12 @@ xfs_iomap_write_allocate( | |||
676 | * See if we were able to allocate an extent that | 674 | * See if we were able to allocate an extent that |
677 | * covers at least part of the callers request | 675 | * covers at least part of the callers request |
678 | */ | 676 | */ |
679 | if (!(imap.br_startblock || XFS_IS_REALTIME_INODE(ip))) | 677 | if (!(imap->br_startblock || XFS_IS_REALTIME_INODE(ip))) |
680 | return xfs_cmn_err_fsblock_zero(ip, &imap); | 678 | return xfs_cmn_err_fsblock_zero(ip, imap); |
681 | 679 | ||
682 | if ((offset_fsb >= imap.br_startoff) && | 680 | if ((offset_fsb >= imap->br_startoff) && |
683 | (offset_fsb < (imap.br_startoff + | 681 | (offset_fsb < (imap->br_startoff + |
684 | imap.br_blockcount))) { | 682 | imap->br_blockcount))) { |
685 | *map = imap; | ||
686 | *retmap = 1; | 683 | *retmap = 1; |
687 | XFS_STATS_INC(xs_xstrat_quick); | 684 | XFS_STATS_INC(xs_xstrat_quick); |
688 | return 0; | 685 | return 0; |
@@ -692,8 +689,8 @@ xfs_iomap_write_allocate( | |||
692 | * So far we have not mapped the requested part of the | 689 | * So far we have not mapped the requested part of the |
693 | * file, just surrounding data, try again. | 690 | * file, just surrounding data, try again. |
694 | */ | 691 | */ |
695 | count_fsb -= imap.br_blockcount; | 692 | count_fsb -= imap->br_blockcount; |
696 | map_start_fsb = imap.br_startoff + imap.br_blockcount; | 693 | map_start_fsb = imap->br_startoff + imap->br_blockcount; |
697 | } | 694 | } |
698 | 695 | ||
699 | trans_cancel: | 696 | trans_cancel: |
@@ -766,8 +763,7 @@ xfs_iomap_write_unwritten( | |||
766 | } | 763 | } |
767 | 764 | ||
768 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 765 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
769 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 766 | xfs_trans_ijoin(tp, ip); |
770 | xfs_trans_ihold(tp, ip); | ||
771 | 767 | ||
772 | /* | 768 | /* |
773 | * Modify the unwritten extent state of the buffer. | 769 | * Modify the unwritten extent state of the buffer. |
@@ -776,7 +772,7 @@ xfs_iomap_write_unwritten( | |||
776 | nimaps = 1; | 772 | nimaps = 1; |
777 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, | 773 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, |
778 | XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, | 774 | XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, |
779 | 1, &imap, &nimaps, &free_list, NULL); | 775 | 1, &imap, &nimaps, &free_list); |
780 | if (error) | 776 | if (error) |
781 | goto error_on_bmapi_transaction; | 777 | goto error_on_bmapi_transaction; |
782 | 778 | ||
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index 81ac4afd45b3..7748a430f50d 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h | |||
@@ -18,17 +18,16 @@ | |||
18 | #ifndef __XFS_IOMAP_H__ | 18 | #ifndef __XFS_IOMAP_H__ |
19 | #define __XFS_IOMAP_H__ | 19 | #define __XFS_IOMAP_H__ |
20 | 20 | ||
21 | typedef enum { | 21 | /* base extent manipulation calls */ |
22 | /* base extent manipulation calls */ | 22 | #define BMAPI_READ (1 << 0) /* read extents */ |
23 | BMAPI_READ = (1 << 0), /* read extents */ | 23 | #define BMAPI_WRITE (1 << 1) /* create extents */ |
24 | BMAPI_WRITE = (1 << 1), /* create extents */ | 24 | #define BMAPI_ALLOCATE (1 << 2) /* delayed allocate to real extents */ |
25 | BMAPI_ALLOCATE = (1 << 2), /* delayed allocate to real extents */ | 25 | |
26 | /* modifiers */ | 26 | /* modifiers */ |
27 | BMAPI_IGNSTATE = (1 << 4), /* ignore unwritten state on read */ | 27 | #define BMAPI_IGNSTATE (1 << 4) /* ignore unwritten state on read */ |
28 | BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */ | 28 | #define BMAPI_DIRECT (1 << 5) /* direct instead of buffered write */ |
29 | BMAPI_MMAP = (1 << 6), /* allocate for mmap write */ | 29 | #define BMAPI_MMA (1 << 6) /* allocate for mmap write */ |
30 | BMAPI_TRYLOCK = (1 << 7), /* non-blocking request */ | 30 | #define BMAPI_TRYLOCK (1 << 7) /* non-blocking request */ |
31 | } bmapi_flags_t; | ||
32 | 31 | ||
33 | #define BMAPI_FLAGS \ | 32 | #define BMAPI_FLAGS \ |
34 | { BMAPI_READ, "READ" }, \ | 33 | { BMAPI_READ, "READ" }, \ |
@@ -36,7 +35,6 @@ typedef enum { | |||
36 | { BMAPI_ALLOCATE, "ALLOCATE" }, \ | 35 | { BMAPI_ALLOCATE, "ALLOCATE" }, \ |
37 | { BMAPI_IGNSTATE, "IGNSTATE" }, \ | 36 | { BMAPI_IGNSTATE, "IGNSTATE" }, \ |
38 | { BMAPI_DIRECT, "DIRECT" }, \ | 37 | { BMAPI_DIRECT, "DIRECT" }, \ |
39 | { BMAPI_MMAP, "MMAP" }, \ | ||
40 | { BMAPI_TRYLOCK, "TRYLOCK" } | 38 | { BMAPI_TRYLOCK, "TRYLOCK" } |
41 | 39 | ||
42 | struct xfs_inode; | 40 | struct xfs_inode; |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 2b86f8610512..7e3626e5925c 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -24,20 +24,17 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
37 | #include "xfs_ialloc.h" | 33 | #include "xfs_ialloc.h" |
38 | #include "xfs_itable.h" | 34 | #include "xfs_itable.h" |
39 | #include "xfs_error.h" | 35 | #include "xfs_error.h" |
40 | #include "xfs_btree.h" | 36 | #include "xfs_btree.h" |
37 | #include "xfs_trace.h" | ||
41 | 38 | ||
42 | STATIC int | 39 | STATIC int |
43 | xfs_internal_inum( | 40 | xfs_internal_inum( |
@@ -143,7 +140,8 @@ xfs_bulkstat_one_int( | |||
143 | buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks; | 140 | buf->bs_blocks = dic->di_nblocks + ip->i_delayed_blks; |
144 | break; | 141 | break; |
145 | } | 142 | } |
146 | xfs_iput(ip, XFS_ILOCK_SHARED); | 143 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
144 | IRELE(ip); | ||
147 | 145 | ||
148 | error = formatter(buffer, ubsize, ubused, buf); | 146 | error = formatter(buffer, ubsize, ubused, buf); |
149 | 147 | ||
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 5215abc8023a..925d572bf0f4 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -24,8 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_error.h" | 28 | #include "xfs_error.h" |
31 | #include "xfs_log_priv.h" | 29 | #include "xfs_log_priv.h" |
@@ -35,8 +33,6 @@ | |||
35 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
36 | #include "xfs_log_recover.h" | 34 | #include "xfs_log_recover.h" |
37 | #include "xfs_trans_priv.h" | 35 | #include "xfs_trans_priv.h" |
38 | #include "xfs_dir2_sf.h" | ||
39 | #include "xfs_attr_sf.h" | ||
40 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
41 | #include "xfs_inode.h" | 37 | #include "xfs_inode.h" |
42 | #include "xfs_rw.h" | 38 | #include "xfs_rw.h" |
@@ -337,7 +333,6 @@ xfs_log_reserve( | |||
337 | int retval = 0; | 333 | int retval = 0; |
338 | 334 | ||
339 | ASSERT(client == XFS_TRANSACTION || client == XFS_LOG); | 335 | ASSERT(client == XFS_TRANSACTION || client == XFS_LOG); |
340 | ASSERT((flags & XFS_LOG_NOSLEEP) == 0); | ||
341 | 336 | ||
342 | if (XLOG_FORCED_SHUTDOWN(log)) | 337 | if (XLOG_FORCED_SHUTDOWN(log)) |
343 | return XFS_ERROR(EIO); | 338 | return XFS_ERROR(EIO); |
@@ -552,7 +547,7 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
552 | .magic = XLOG_UNMOUNT_TYPE, | 547 | .magic = XLOG_UNMOUNT_TYPE, |
553 | }; | 548 | }; |
554 | struct xfs_log_iovec reg = { | 549 | struct xfs_log_iovec reg = { |
555 | .i_addr = (void *)&magic, | 550 | .i_addr = &magic, |
556 | .i_len = sizeof(magic), | 551 | .i_len = sizeof(magic), |
557 | .i_type = XLOG_REG_TYPE_UNMOUNT, | 552 | .i_type = XLOG_REG_TYPE_UNMOUNT, |
558 | }; | 553 | }; |
@@ -1047,7 +1042,6 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1047 | xlog_in_core_t *iclog, *prev_iclog=NULL; | 1042 | xlog_in_core_t *iclog, *prev_iclog=NULL; |
1048 | xfs_buf_t *bp; | 1043 | xfs_buf_t *bp; |
1049 | int i; | 1044 | int i; |
1050 | int iclogsize; | ||
1051 | int error = ENOMEM; | 1045 | int error = ENOMEM; |
1052 | uint log2_size = 0; | 1046 | uint log2_size = 0; |
1053 | 1047 | ||
@@ -1127,7 +1121,6 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1127 | * with different amounts of memory. See the definition of | 1121 | * with different amounts of memory. See the definition of |
1128 | * xlog_in_core_t in xfs_log_priv.h for details. | 1122 | * xlog_in_core_t in xfs_log_priv.h for details. |
1129 | */ | 1123 | */ |
1130 | iclogsize = log->l_iclog_size; | ||
1131 | ASSERT(log->l_iclog_size >= 4096); | 1124 | ASSERT(log->l_iclog_size >= 4096); |
1132 | for (i=0; i < log->l_iclog_bufs; i++) { | 1125 | for (i=0; i < log->l_iclog_bufs; i++) { |
1133 | *iclogp = kmem_zalloc(sizeof(xlog_in_core_t), KM_MAYFAIL); | 1126 | *iclogp = kmem_zalloc(sizeof(xlog_in_core_t), KM_MAYFAIL); |
@@ -1428,11 +1421,8 @@ xlog_sync(xlog_t *log, | |||
1428 | XFS_BUF_BUSY(bp); | 1421 | XFS_BUF_BUSY(bp); |
1429 | XFS_BUF_ASYNC(bp); | 1422 | XFS_BUF_ASYNC(bp); |
1430 | bp->b_flags |= XBF_LOG_BUFFER; | 1423 | bp->b_flags |= XBF_LOG_BUFFER; |
1431 | /* | 1424 | |
1432 | * Do an ordered write for the log block. | 1425 | if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) |
1433 | * Its unnecessary to flush the first split block in the log wrap case. | ||
1434 | */ | ||
1435 | if (!split && (log->l_mp->m_flags & XFS_MOUNT_BARRIER)) | ||
1436 | XFS_BUF_ORDERED(bp); | 1426 | XFS_BUF_ORDERED(bp); |
1437 | 1427 | ||
1438 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); | 1428 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); |
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index 04c78e642cc8..916eb7db14d9 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h | |||
@@ -55,14 +55,10 @@ static inline xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2) | |||
55 | /* | 55 | /* |
56 | * Flags to xfs_log_reserve() | 56 | * Flags to xfs_log_reserve() |
57 | * | 57 | * |
58 | * XFS_LOG_SLEEP: If space is not available, sleep (default) | ||
59 | * XFS_LOG_NOSLEEP: If space is not available, return error | ||
60 | * XFS_LOG_PERM_RESERV: Permanent reservation. When writes are | 58 | * XFS_LOG_PERM_RESERV: Permanent reservation. When writes are |
61 | * performed against this type of reservation, the reservation | 59 | * performed against this type of reservation, the reservation |
62 | * is not decreased. Long running transactions should use this. | 60 | * is not decreased. Long running transactions should use this. |
63 | */ | 61 | */ |
64 | #define XFS_LOG_SLEEP 0x0 | ||
65 | #define XFS_LOG_NOSLEEP 0x1 | ||
66 | #define XFS_LOG_PERM_RESERV 0x2 | 62 | #define XFS_LOG_PERM_RESERV 0x2 |
67 | 63 | ||
68 | /* | 64 | /* |
@@ -104,7 +100,7 @@ static inline xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2) | |||
104 | #define XLOG_REG_TYPE_MAX 19 | 100 | #define XLOG_REG_TYPE_MAX 19 |
105 | 101 | ||
106 | typedef struct xfs_log_iovec { | 102 | typedef struct xfs_log_iovec { |
107 | xfs_caddr_t i_addr; /* beginning address of region */ | 103 | void *i_addr; /* beginning address of region */ |
108 | int i_len; /* length in bytes of region */ | 104 | int i_len; /* length in bytes of region */ |
109 | uint i_type; /* type of region */ | 105 | uint i_type; /* type of region */ |
110 | } xfs_log_iovec_t; | 106 | } xfs_log_iovec_t; |
@@ -201,9 +197,4 @@ int xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp, | |||
201 | bool xfs_log_item_in_current_chkpt(struct xfs_log_item *lip); | 197 | bool xfs_log_item_in_current_chkpt(struct xfs_log_item *lip); |
202 | 198 | ||
203 | #endif | 199 | #endif |
204 | |||
205 | |||
206 | extern int xlog_debug; /* set to 1 to enable real log */ | ||
207 | |||
208 | |||
209 | #endif /* __XFS_LOG_H__ */ | 200 | #endif /* __XFS_LOG_H__ */ |
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index bb17cc044bf3..31e4ea2d19ac 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c | |||
@@ -26,8 +26,6 @@ | |||
26 | #include "xfs_log_priv.h" | 26 | #include "xfs_log_priv.h" |
27 | #include "xfs_sb.h" | 27 | #include "xfs_sb.h" |
28 | #include "xfs_ag.h" | 28 | #include "xfs_ag.h" |
29 | #include "xfs_dir2.h" | ||
30 | #include "xfs_dmapi.h" | ||
31 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
32 | #include "xfs_error.h" | 30 | #include "xfs_error.h" |
33 | #include "xfs_alloc.h" | 31 | #include "xfs_alloc.h" |
@@ -554,7 +552,7 @@ xlog_cil_push( | |||
554 | thdr.th_type = XFS_TRANS_CHECKPOINT; | 552 | thdr.th_type = XFS_TRANS_CHECKPOINT; |
555 | thdr.th_tid = tic->t_tid; | 553 | thdr.th_tid = tic->t_tid; |
556 | thdr.th_num_items = num_iovecs; | 554 | thdr.th_num_items = num_iovecs; |
557 | lhdr.i_addr = (xfs_caddr_t)&thdr; | 555 | lhdr.i_addr = &thdr; |
558 | lhdr.i_len = sizeof(xfs_trans_header_t); | 556 | lhdr.i_len = sizeof(xfs_trans_header_t); |
559 | lhdr.i_type = XLOG_REG_TYPE_TRANSHDR; | 557 | lhdr.i_type = XLOG_REG_TYPE_TRANSHDR; |
560 | tic->t_curr_res -= lhdr.i_len + sizeof(xlog_op_header_t); | 558 | tic->t_curr_res -= lhdr.i_len + sizeof(xlog_op_header_t); |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 9ac5cfab27b9..6f3f5fa37acf 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -24,15 +24,11 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_error.h" | 28 | #include "xfs_error.h" |
31 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 30 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 31 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
37 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
38 | #include "xfs_inode_item.h" | 34 | #include "xfs_inode_item.h" |
@@ -1565,9 +1561,7 @@ xlog_recover_reorder_trans( | |||
1565 | 1561 | ||
1566 | list_splice_init(&trans->r_itemq, &sort_list); | 1562 | list_splice_init(&trans->r_itemq, &sort_list); |
1567 | list_for_each_entry_safe(item, n, &sort_list, ri_list) { | 1563 | list_for_each_entry_safe(item, n, &sort_list, ri_list) { |
1568 | xfs_buf_log_format_t *buf_f; | 1564 | xfs_buf_log_format_t *buf_f = item->ri_buf[0].i_addr; |
1569 | |||
1570 | buf_f = (xfs_buf_log_format_t *)item->ri_buf[0].i_addr; | ||
1571 | 1565 | ||
1572 | switch (ITEM_TYPE(item)) { | 1566 | switch (ITEM_TYPE(item)) { |
1573 | case XFS_LI_BUF: | 1567 | case XFS_LI_BUF: |
@@ -1892,9 +1886,8 @@ xlog_recover_do_inode_buffer( | |||
1892 | * current di_next_unlinked field. Extract its value | 1886 | * current di_next_unlinked field. Extract its value |
1893 | * and copy it to the buffer copy. | 1887 | * and copy it to the buffer copy. |
1894 | */ | 1888 | */ |
1895 | logged_nextp = (xfs_agino_t *) | 1889 | logged_nextp = item->ri_buf[item_index].i_addr + |
1896 | ((char *)(item->ri_buf[item_index].i_addr) + | 1890 | next_unlinked_offset - reg_buf_offset; |
1897 | (next_unlinked_offset - reg_buf_offset)); | ||
1898 | if (unlikely(*logged_nextp == 0)) { | 1891 | if (unlikely(*logged_nextp == 0)) { |
1899 | xfs_fs_cmn_err(CE_ALERT, mp, | 1892 | xfs_fs_cmn_err(CE_ALERT, mp, |
1900 | "bad inode buffer log record (ptr = 0x%p, bp = 0x%p). XFS trying to replay bad (0) inode di_next_unlinked field", | 1893 | "bad inode buffer log record (ptr = 0x%p, bp = 0x%p). XFS trying to replay bad (0) inode di_next_unlinked field", |
@@ -1973,8 +1966,7 @@ xlog_recover_do_reg_buffer( | |||
1973 | item->ri_buf[i].i_len, __func__); | 1966 | item->ri_buf[i].i_len, __func__); |
1974 | goto next; | 1967 | goto next; |
1975 | } | 1968 | } |
1976 | error = xfs_qm_dqcheck((xfs_disk_dquot_t *) | 1969 | error = xfs_qm_dqcheck(item->ri_buf[i].i_addr, |
1977 | item->ri_buf[i].i_addr, | ||
1978 | -1, 0, XFS_QMOPT_DOWARN, | 1970 | -1, 0, XFS_QMOPT_DOWARN, |
1979 | "dquot_buf_recover"); | 1971 | "dquot_buf_recover"); |
1980 | if (error) | 1972 | if (error) |
@@ -2187,7 +2179,7 @@ xlog_recover_do_buffer_trans( | |||
2187 | xlog_recover_item_t *item, | 2179 | xlog_recover_item_t *item, |
2188 | int pass) | 2180 | int pass) |
2189 | { | 2181 | { |
2190 | xfs_buf_log_format_t *buf_f; | 2182 | xfs_buf_log_format_t *buf_f = item->ri_buf[0].i_addr; |
2191 | xfs_mount_t *mp; | 2183 | xfs_mount_t *mp; |
2192 | xfs_buf_t *bp; | 2184 | xfs_buf_t *bp; |
2193 | int error; | 2185 | int error; |
@@ -2197,8 +2189,6 @@ xlog_recover_do_buffer_trans( | |||
2197 | ushort flags; | 2189 | ushort flags; |
2198 | uint buf_flags; | 2190 | uint buf_flags; |
2199 | 2191 | ||
2200 | buf_f = (xfs_buf_log_format_t *)item->ri_buf[0].i_addr; | ||
2201 | |||
2202 | if (pass == XLOG_RECOVER_PASS1) { | 2192 | if (pass == XLOG_RECOVER_PASS1) { |
2203 | /* | 2193 | /* |
2204 | * In this pass we're only looking for buf items | 2194 | * In this pass we're only looking for buf items |
@@ -2319,10 +2309,9 @@ xlog_recover_do_inode_trans( | |||
2319 | } | 2309 | } |
2320 | 2310 | ||
2321 | if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) { | 2311 | if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) { |
2322 | in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr; | 2312 | in_f = item->ri_buf[0].i_addr; |
2323 | } else { | 2313 | } else { |
2324 | in_f = (xfs_inode_log_format_t *)kmem_alloc( | 2314 | in_f = kmem_alloc(sizeof(xfs_inode_log_format_t), KM_SLEEP); |
2325 | sizeof(xfs_inode_log_format_t), KM_SLEEP); | ||
2326 | need_free = 1; | 2315 | need_free = 1; |
2327 | error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f); | 2316 | error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f); |
2328 | if (error) | 2317 | if (error) |
@@ -2370,7 +2359,7 @@ xlog_recover_do_inode_trans( | |||
2370 | error = EFSCORRUPTED; | 2359 | error = EFSCORRUPTED; |
2371 | goto error; | 2360 | goto error; |
2372 | } | 2361 | } |
2373 | dicp = (xfs_icdinode_t *)(item->ri_buf[1].i_addr); | 2362 | dicp = item->ri_buf[1].i_addr; |
2374 | if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { | 2363 | if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { |
2375 | xfs_buf_relse(bp); | 2364 | xfs_buf_relse(bp); |
2376 | xfs_fs_cmn_err(CE_ALERT, mp, | 2365 | xfs_fs_cmn_err(CE_ALERT, mp, |
@@ -2461,7 +2450,7 @@ xlog_recover_do_inode_trans( | |||
2461 | } | 2450 | } |
2462 | 2451 | ||
2463 | /* The core is in in-core format */ | 2452 | /* The core is in in-core format */ |
2464 | xfs_dinode_to_disk(dip, (xfs_icdinode_t *)item->ri_buf[1].i_addr); | 2453 | xfs_dinode_to_disk(dip, item->ri_buf[1].i_addr); |
2465 | 2454 | ||
2466 | /* the rest is in on-disk format */ | 2455 | /* the rest is in on-disk format */ |
2467 | if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) { | 2456 | if (item->ri_buf[1].i_len > sizeof(struct xfs_icdinode)) { |
@@ -2578,7 +2567,7 @@ xlog_recover_do_quotaoff_trans( | |||
2578 | return (0); | 2567 | return (0); |
2579 | } | 2568 | } |
2580 | 2569 | ||
2581 | qoff_f = (xfs_qoff_logformat_t *)item->ri_buf[0].i_addr; | 2570 | qoff_f = item->ri_buf[0].i_addr; |
2582 | ASSERT(qoff_f); | 2571 | ASSERT(qoff_f); |
2583 | 2572 | ||
2584 | /* | 2573 | /* |
@@ -2622,9 +2611,8 @@ xlog_recover_do_dquot_trans( | |||
2622 | if (mp->m_qflags == 0) | 2611 | if (mp->m_qflags == 0) |
2623 | return (0); | 2612 | return (0); |
2624 | 2613 | ||
2625 | recddq = (xfs_disk_dquot_t *)item->ri_buf[1].i_addr; | 2614 | recddq = item->ri_buf[1].i_addr; |
2626 | 2615 | if (recddq == NULL) { | |
2627 | if (item->ri_buf[1].i_addr == NULL) { | ||
2628 | cmn_err(CE_ALERT, | 2616 | cmn_err(CE_ALERT, |
2629 | "XFS: NULL dquot in %s.", __func__); | 2617 | "XFS: NULL dquot in %s.", __func__); |
2630 | return XFS_ERROR(EIO); | 2618 | return XFS_ERROR(EIO); |
@@ -2654,7 +2642,7 @@ xlog_recover_do_dquot_trans( | |||
2654 | * The other possibility, of course, is that the quota subsystem was | 2642 | * The other possibility, of course, is that the quota subsystem was |
2655 | * removed since the last mount - ENOSYS. | 2643 | * removed since the last mount - ENOSYS. |
2656 | */ | 2644 | */ |
2657 | dq_f = (xfs_dq_logformat_t *)item->ri_buf[0].i_addr; | 2645 | dq_f = item->ri_buf[0].i_addr; |
2658 | ASSERT(dq_f); | 2646 | ASSERT(dq_f); |
2659 | if ((error = xfs_qm_dqcheck(recddq, | 2647 | if ((error = xfs_qm_dqcheck(recddq, |
2660 | dq_f->qlf_id, | 2648 | dq_f->qlf_id, |
@@ -2721,7 +2709,7 @@ xlog_recover_do_efi_trans( | |||
2721 | return 0; | 2709 | return 0; |
2722 | } | 2710 | } |
2723 | 2711 | ||
2724 | efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; | 2712 | efi_formatp = item->ri_buf[0].i_addr; |
2725 | 2713 | ||
2726 | mp = log->l_mp; | 2714 | mp = log->l_mp; |
2727 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); | 2715 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); |
@@ -2767,7 +2755,7 @@ xlog_recover_do_efd_trans( | |||
2767 | return; | 2755 | return; |
2768 | } | 2756 | } |
2769 | 2757 | ||
2770 | efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; | 2758 | efd_formatp = item->ri_buf[0].i_addr; |
2771 | ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) + | 2759 | ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) + |
2772 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) || | 2760 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) || |
2773 | (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) + | 2761 | (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) + |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 69f62d8b2816..aeb9d72ebf6e 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -25,13 +25,10 @@ | |||
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 30 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 31 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
37 | #include "xfs_btree.h" | 34 | #include "xfs_btree.h" |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 1d2c7eed4eda..622da2179a57 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -66,65 +66,6 @@ struct xfs_nameops; | |||
66 | struct xfs_ail; | 66 | struct xfs_ail; |
67 | struct xfs_quotainfo; | 67 | struct xfs_quotainfo; |
68 | 68 | ||
69 | |||
70 | /* | ||
71 | * Prototypes and functions for the Data Migration subsystem. | ||
72 | */ | ||
73 | |||
74 | typedef int (*xfs_send_data_t)(int, struct xfs_inode *, | ||
75 | xfs_off_t, size_t, int, int *); | ||
76 | typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint); | ||
77 | typedef int (*xfs_send_destroy_t)(struct xfs_inode *, dm_right_t); | ||
78 | typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct xfs_mount *, | ||
79 | struct xfs_inode *, dm_right_t, | ||
80 | struct xfs_inode *, dm_right_t, | ||
81 | const unsigned char *, const unsigned char *, | ||
82 | mode_t, int, int); | ||
83 | typedef int (*xfs_send_mount_t)(struct xfs_mount *, dm_right_t, | ||
84 | char *, char *); | ||
85 | typedef void (*xfs_send_unmount_t)(struct xfs_mount *, struct xfs_inode *, | ||
86 | dm_right_t, mode_t, int, int); | ||
87 | |||
88 | typedef struct xfs_dmops { | ||
89 | xfs_send_data_t xfs_send_data; | ||
90 | xfs_send_mmap_t xfs_send_mmap; | ||
91 | xfs_send_destroy_t xfs_send_destroy; | ||
92 | xfs_send_namesp_t xfs_send_namesp; | ||
93 | xfs_send_mount_t xfs_send_mount; | ||
94 | xfs_send_unmount_t xfs_send_unmount; | ||
95 | } xfs_dmops_t; | ||
96 | |||
97 | #define XFS_DMAPI_UNMOUNT_FLAGS(mp) \ | ||
98 | (((mp)->m_dmevmask & (1 << DM_EVENT_UNMOUNT)) ? 0 : DM_FLAGS_UNWANTED) | ||
99 | |||
100 | #define XFS_SEND_DATA(mp, ev,ip,off,len,fl,lock) \ | ||
101 | (*(mp)->m_dm_ops->xfs_send_data)(ev,ip,off,len,fl,lock) | ||
102 | #define XFS_SEND_MMAP(mp, vma,fl) \ | ||
103 | (*(mp)->m_dm_ops->xfs_send_mmap)(vma,fl) | ||
104 | #define XFS_SEND_DESTROY(mp, ip,right) \ | ||
105 | (*(mp)->m_dm_ops->xfs_send_destroy)(ip,right) | ||
106 | #define XFS_SEND_NAMESP(mp, ev,b1,r1,b2,r2,n1,n2,mode,rval,fl) \ | ||
107 | (*(mp)->m_dm_ops->xfs_send_namesp)(ev,NULL,b1,r1,b2,r2,n1,n2,mode,rval,fl) | ||
108 | #define XFS_SEND_MOUNT(mp,right,path,name) \ | ||
109 | (*(mp)->m_dm_ops->xfs_send_mount)(mp,right,path,name) | ||
110 | #define XFS_SEND_PREUNMOUNT(mp) \ | ||
111 | do { \ | ||
112 | if (mp->m_flags & XFS_MOUNT_DMAPI) { \ | ||
113 | (*(mp)->m_dm_ops->xfs_send_namesp)(DM_EVENT_PREUNMOUNT, mp, \ | ||
114 | (mp)->m_rootip, DM_RIGHT_NULL, \ | ||
115 | (mp)->m_rootip, DM_RIGHT_NULL, \ | ||
116 | NULL, NULL, 0, 0, XFS_DMAPI_UNMOUNT_FLAGS(mp)); \ | ||
117 | } \ | ||
118 | } while (0) | ||
119 | #define XFS_SEND_UNMOUNT(mp) \ | ||
120 | do { \ | ||
121 | if (mp->m_flags & XFS_MOUNT_DMAPI) { \ | ||
122 | (*(mp)->m_dm_ops->xfs_send_unmount)(mp, (mp)->m_rootip, \ | ||
123 | DM_RIGHT_NULL, 0, 0, XFS_DMAPI_UNMOUNT_FLAGS(mp)); \ | ||
124 | } \ | ||
125 | } while (0) | ||
126 | |||
127 | |||
128 | #ifdef HAVE_PERCPU_SB | 69 | #ifdef HAVE_PERCPU_SB |
129 | 70 | ||
130 | /* | 71 | /* |
@@ -241,8 +182,6 @@ typedef struct xfs_mount { | |||
241 | uint m_chsize; /* size of next field */ | 182 | uint m_chsize; /* size of next field */ |
242 | struct xfs_chash *m_chash; /* fs private inode per-cluster | 183 | struct xfs_chash *m_chash; /* fs private inode per-cluster |
243 | * hash table */ | 184 | * hash table */ |
244 | struct xfs_dmops *m_dm_ops; /* vector of DMI ops */ | ||
245 | struct xfs_qmops *m_qm_ops; /* vector of XQM ops */ | ||
246 | atomic_t m_active_trans; /* number trans frozen */ | 185 | atomic_t m_active_trans; /* number trans frozen */ |
247 | #ifdef HAVE_PERCPU_SB | 186 | #ifdef HAVE_PERCPU_SB |
248 | xfs_icsb_cnts_t __percpu *m_sb_cnts; /* per-cpu superblock counters */ | 187 | xfs_icsb_cnts_t __percpu *m_sb_cnts; /* per-cpu superblock counters */ |
@@ -259,7 +198,7 @@ typedef struct xfs_mount { | |||
259 | wait_queue_head_t m_wait_single_sync_task; | 198 | wait_queue_head_t m_wait_single_sync_task; |
260 | __int64_t m_update_flags; /* sb flags we need to update | 199 | __int64_t m_update_flags; /* sb flags we need to update |
261 | on the next remount,rw */ | 200 | on the next remount,rw */ |
262 | struct list_head m_mplist; /* inode shrinker mount list */ | 201 | struct shrinker m_inode_shrink; /* inode reclaim shrinker */ |
263 | } xfs_mount_t; | 202 | } xfs_mount_t; |
264 | 203 | ||
265 | /* | 204 | /* |
@@ -269,7 +208,6 @@ typedef struct xfs_mount { | |||
269 | must be synchronous except | 208 | must be synchronous except |
270 | for space allocations */ | 209 | for space allocations */ |
271 | #define XFS_MOUNT_DELAYLOG (1ULL << 1) /* delayed logging is enabled */ | 210 | #define XFS_MOUNT_DELAYLOG (1ULL << 1) /* delayed logging is enabled */ |
272 | #define XFS_MOUNT_DMAPI (1ULL << 2) /* dmapi is enabled */ | ||
273 | #define XFS_MOUNT_WAS_CLEAN (1ULL << 3) | 211 | #define XFS_MOUNT_WAS_CLEAN (1ULL << 3) |
274 | #define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem | 212 | #define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem |
275 | operations, typically for | 213 | operations, typically for |
@@ -282,8 +220,6 @@ typedef struct xfs_mount { | |||
282 | #define XFS_MOUNT_GRPID (1ULL << 9) /* group-ID assigned from directory */ | 220 | #define XFS_MOUNT_GRPID (1ULL << 9) /* group-ID assigned from directory */ |
283 | #define XFS_MOUNT_NORECOVERY (1ULL << 10) /* no recovery - dirty fs */ | 221 | #define XFS_MOUNT_NORECOVERY (1ULL << 10) /* no recovery - dirty fs */ |
284 | #define XFS_MOUNT_DFLT_IOSIZE (1ULL << 12) /* set default i/o size */ | 222 | #define XFS_MOUNT_DFLT_IOSIZE (1ULL << 12) /* set default i/o size */ |
285 | #define XFS_MOUNT_OSYNCISOSYNC (1ULL << 13) /* o_sync is REALLY o_sync */ | ||
286 | /* osyncisdsync is now default*/ | ||
287 | #define XFS_MOUNT_32BITINODES (1ULL << 14) /* do not create inodes above | 223 | #define XFS_MOUNT_32BITINODES (1ULL << 14) /* do not create inodes above |
288 | * 32 bits in size */ | 224 | * 32 bits in size */ |
289 | #define XFS_MOUNT_SMALL_INUMS (1ULL << 15) /* users wants 32bit inodes */ | 225 | #define XFS_MOUNT_SMALL_INUMS (1ULL << 15) /* users wants 32bit inodes */ |
@@ -440,11 +376,6 @@ extern int xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t); | |||
440 | 376 | ||
441 | extern int xfs_dev_is_read_only(struct xfs_mount *, char *); | 377 | extern int xfs_dev_is_read_only(struct xfs_mount *, char *); |
442 | 378 | ||
443 | extern int xfs_dmops_get(struct xfs_mount *); | ||
444 | extern void xfs_dmops_put(struct xfs_mount *); | ||
445 | |||
446 | extern struct xfs_dmops xfs_dmcore_xfs; | ||
447 | |||
448 | #endif /* __KERNEL__ */ | 379 | #endif /* __KERNEL__ */ |
449 | 380 | ||
450 | extern void xfs_mod_sb(struct xfs_trans *, __int64_t); | 381 | extern void xfs_mod_sb(struct xfs_trans *, __int64_t); |
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index fc1cda23b817..8fca957200df 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c | |||
@@ -24,12 +24,9 @@ | |||
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_dir2_sf.h" | ||
32 | #include "xfs_attr_sf.h" | ||
33 | #include "xfs_dinode.h" | 30 | #include "xfs_dinode.h" |
34 | #include "xfs_inode.h" | 31 | #include "xfs_inode.h" |
35 | #include "xfs_inode_item.h" | 32 | #include "xfs_inode_item.h" |
@@ -116,20 +113,7 @@ xfs_rename( | |||
116 | int spaceres; | 113 | int spaceres; |
117 | int num_inodes; | 114 | int num_inodes; |
118 | 115 | ||
119 | xfs_itrace_entry(src_dp); | 116 | trace_xfs_rename(src_dp, target_dp, src_name, target_name); |
120 | xfs_itrace_entry(target_dp); | ||
121 | |||
122 | if (DM_EVENT_ENABLED(src_dp, DM_EVENT_RENAME) || | ||
123 | DM_EVENT_ENABLED(target_dp, DM_EVENT_RENAME)) { | ||
124 | error = XFS_SEND_NAMESP(mp, DM_EVENT_RENAME, | ||
125 | src_dp, DM_RIGHT_NULL, | ||
126 | target_dp, DM_RIGHT_NULL, | ||
127 | src_name->name, target_name->name, | ||
128 | 0, 0, 0); | ||
129 | if (error) | ||
130 | return error; | ||
131 | } | ||
132 | /* Return through std_return after this point. */ | ||
133 | 117 | ||
134 | new_parent = (src_dp != target_dp); | 118 | new_parent = (src_dp != target_dp); |
135 | src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR); | 119 | src_is_directory = ((src_ip->i_d.di_mode & S_IFMT) == S_IFDIR); |
@@ -184,26 +168,14 @@ xfs_rename( | |||
184 | /* | 168 | /* |
185 | * Join all the inodes to the transaction. From this point on, | 169 | * Join all the inodes to the transaction. From this point on, |
186 | * we can rely on either trans_commit or trans_cancel to unlock | 170 | * we can rely on either trans_commit or trans_cancel to unlock |
187 | * them. Note that we need to add a vnode reference to the | 171 | * them. |
188 | * directories since trans_commit & trans_cancel will decrement | ||
189 | * them when they unlock the inodes. Also, we need to be careful | ||
190 | * not to add an inode to the transaction more than once. | ||
191 | */ | 172 | */ |
192 | IHOLD(src_dp); | 173 | xfs_trans_ijoin_ref(tp, src_dp, XFS_ILOCK_EXCL); |
193 | xfs_trans_ijoin(tp, src_dp, XFS_ILOCK_EXCL); | 174 | if (new_parent) |
194 | 175 | xfs_trans_ijoin_ref(tp, target_dp, XFS_ILOCK_EXCL); | |
195 | if (new_parent) { | 176 | xfs_trans_ijoin_ref(tp, src_ip, XFS_ILOCK_EXCL); |
196 | IHOLD(target_dp); | 177 | if (target_ip) |
197 | xfs_trans_ijoin(tp, target_dp, XFS_ILOCK_EXCL); | 178 | xfs_trans_ijoin_ref(tp, target_ip, XFS_ILOCK_EXCL); |
198 | } | ||
199 | |||
200 | IHOLD(src_ip); | ||
201 | xfs_trans_ijoin(tp, src_ip, XFS_ILOCK_EXCL); | ||
202 | |||
203 | if (target_ip) { | ||
204 | IHOLD(target_ip); | ||
205 | xfs_trans_ijoin(tp, target_ip, XFS_ILOCK_EXCL); | ||
206 | } | ||
207 | 179 | ||
208 | /* | 180 | /* |
209 | * If we are using project inheritance, we only allow renames | 181 | * If we are using project inheritance, we only allow renames |
@@ -369,26 +341,13 @@ xfs_rename( | |||
369 | * trans_commit will unlock src_ip, target_ip & decrement | 341 | * trans_commit will unlock src_ip, target_ip & decrement |
370 | * the vnode references. | 342 | * the vnode references. |
371 | */ | 343 | */ |
372 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | 344 | return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); |
373 | |||
374 | /* Fall through to std_return with error = 0 or errno from | ||
375 | * xfs_trans_commit */ | ||
376 | std_return: | ||
377 | if (DM_EVENT_ENABLED(src_dp, DM_EVENT_POSTRENAME) || | ||
378 | DM_EVENT_ENABLED(target_dp, DM_EVENT_POSTRENAME)) { | ||
379 | (void) XFS_SEND_NAMESP (mp, DM_EVENT_POSTRENAME, | ||
380 | src_dp, DM_RIGHT_NULL, | ||
381 | target_dp, DM_RIGHT_NULL, | ||
382 | src_name->name, target_name->name, | ||
383 | 0, error, 0); | ||
384 | } | ||
385 | return error; | ||
386 | 345 | ||
387 | abort_return: | 346 | abort_return: |
388 | cancel_flags |= XFS_TRANS_ABORT; | 347 | cancel_flags |= XFS_TRANS_ABORT; |
389 | /* FALLTHROUGH */ | ||
390 | error_return: | 348 | error_return: |
391 | xfs_bmap_cancel(&free_list); | 349 | xfs_bmap_cancel(&free_list); |
392 | xfs_trans_cancel(tp, cancel_flags); | 350 | xfs_trans_cancel(tp, cancel_flags); |
393 | goto std_return; | 351 | std_return: |
352 | return error; | ||
394 | } | 353 | } |
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index a2d32ce335aa..891260fea11e 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c | |||
@@ -25,17 +25,10 @@ | |||
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | ||
32 | #include "xfs_ialloc_btree.h" | ||
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 30 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 31 | #include "xfs_inode.h" |
37 | #include "xfs_btree.h" | ||
38 | #include "xfs_ialloc.h" | ||
39 | #include "xfs_alloc.h" | 32 | #include "xfs_alloc.h" |
40 | #include "xfs_bmap.h" | 33 | #include "xfs_bmap.h" |
41 | #include "xfs_rtalloc.h" | 34 | #include "xfs_rtalloc.h" |
@@ -129,7 +122,7 @@ xfs_growfs_rt_alloc( | |||
129 | cancelflags |= XFS_TRANS_ABORT; | 122 | cancelflags |= XFS_TRANS_ABORT; |
130 | error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks, | 123 | error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks, |
131 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock, | 124 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock, |
132 | resblks, &map, &nmap, &flist, NULL); | 125 | resblks, &map, &nmap, &flist); |
133 | if (!error && nmap < 1) | 126 | if (!error && nmap < 1) |
134 | error = XFS_ERROR(ENOSPC); | 127 | error = XFS_ERROR(ENOSPC); |
135 | if (error) | 128 | if (error) |
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index e336742a58a4..56861d5daaef 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c | |||
@@ -24,27 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | ||
32 | #include "xfs_ialloc_btree.h" | ||
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 29 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 30 | #include "xfs_inode.h" |
37 | #include "xfs_inode_item.h" | ||
38 | #include "xfs_itable.h" | ||
39 | #include "xfs_btree.h" | ||
40 | #include "xfs_alloc.h" | ||
41 | #include "xfs_ialloc.h" | ||
42 | #include "xfs_attr.h" | ||
43 | #include "xfs_bmap.h" | ||
44 | #include "xfs_error.h" | 31 | #include "xfs_error.h" |
45 | #include "xfs_buf_item.h" | ||
46 | #include "xfs_rw.h" | 32 | #include "xfs_rw.h" |
47 | #include "xfs_trace.h" | ||
48 | 33 | ||
49 | /* | 34 | /* |
50 | * Force a shutdown of the filesystem instantly while keeping | 35 | * Force a shutdown of the filesystem instantly while keeping |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 28547dfce037..fdca7416c754 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. |
3 | * Copyright (C) 2010 Red Hat, Inc. | ||
3 | * All Rights Reserved. | 4 | * All Rights Reserved. |
4 | * | 5 | * |
5 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -24,16 +25,12 @@ | |||
24 | #include "xfs_trans.h" | 25 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 26 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 27 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
30 | #include "xfs_error.h" | 29 | #include "xfs_error.h" |
31 | #include "xfs_da_btree.h" | 30 | #include "xfs_da_btree.h" |
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir2_sf.h" | ||
36 | #include "xfs_attr_sf.h" | ||
37 | #include "xfs_dinode.h" | 34 | #include "xfs_dinode.h" |
38 | #include "xfs_inode.h" | 35 | #include "xfs_inode.h" |
39 | #include "xfs_btree.h" | 36 | #include "xfs_btree.h" |
@@ -47,6 +44,7 @@ | |||
47 | #include "xfs_trace.h" | 44 | #include "xfs_trace.h" |
48 | 45 | ||
49 | kmem_zone_t *xfs_trans_zone; | 46 | kmem_zone_t *xfs_trans_zone; |
47 | kmem_zone_t *xfs_log_item_desc_zone; | ||
50 | 48 | ||
51 | 49 | ||
52 | /* | 50 | /* |
@@ -597,8 +595,7 @@ _xfs_trans_alloc( | |||
597 | tp->t_magic = XFS_TRANS_MAGIC; | 595 | tp->t_magic = XFS_TRANS_MAGIC; |
598 | tp->t_type = type; | 596 | tp->t_type = type; |
599 | tp->t_mountp = mp; | 597 | tp->t_mountp = mp; |
600 | tp->t_items_free = XFS_LIC_NUM_SLOTS; | 598 | INIT_LIST_HEAD(&tp->t_items); |
601 | xfs_lic_init(&(tp->t_items)); | ||
602 | INIT_LIST_HEAD(&tp->t_busy); | 599 | INIT_LIST_HEAD(&tp->t_busy); |
603 | return tp; | 600 | return tp; |
604 | } | 601 | } |
@@ -643,8 +640,7 @@ xfs_trans_dup( | |||
643 | ntp->t_magic = XFS_TRANS_MAGIC; | 640 | ntp->t_magic = XFS_TRANS_MAGIC; |
644 | ntp->t_type = tp->t_type; | 641 | ntp->t_type = tp->t_type; |
645 | ntp->t_mountp = tp->t_mountp; | 642 | ntp->t_mountp = tp->t_mountp; |
646 | ntp->t_items_free = XFS_LIC_NUM_SLOTS; | 643 | INIT_LIST_HEAD(&ntp->t_items); |
647 | xfs_lic_init(&(ntp->t_items)); | ||
648 | INIT_LIST_HEAD(&ntp->t_busy); | 644 | INIT_LIST_HEAD(&ntp->t_busy); |
649 | 645 | ||
650 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); | 646 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); |
@@ -1124,6 +1120,108 @@ xfs_trans_unreserve_and_mod_sb( | |||
1124 | } | 1120 | } |
1125 | 1121 | ||
1126 | /* | 1122 | /* |
1123 | * Add the given log item to the transaction's list of log items. | ||
1124 | * | ||
1125 | * The log item will now point to its new descriptor with its li_desc field. | ||
1126 | */ | ||
1127 | void | ||
1128 | xfs_trans_add_item( | ||
1129 | struct xfs_trans *tp, | ||
1130 | struct xfs_log_item *lip) | ||
1131 | { | ||
1132 | struct xfs_log_item_desc *lidp; | ||
1133 | |||
1134 | ASSERT(lip->li_mountp = tp->t_mountp); | ||
1135 | ASSERT(lip->li_ailp = tp->t_mountp->m_ail); | ||
1136 | |||
1137 | lidp = kmem_zone_zalloc(xfs_log_item_desc_zone, KM_SLEEP | KM_NOFS); | ||
1138 | |||
1139 | lidp->lid_item = lip; | ||
1140 | lidp->lid_flags = 0; | ||
1141 | lidp->lid_size = 0; | ||
1142 | list_add_tail(&lidp->lid_trans, &tp->t_items); | ||
1143 | |||
1144 | lip->li_desc = lidp; | ||
1145 | } | ||
1146 | |||
1147 | STATIC void | ||
1148 | xfs_trans_free_item_desc( | ||
1149 | struct xfs_log_item_desc *lidp) | ||
1150 | { | ||
1151 | list_del_init(&lidp->lid_trans); | ||
1152 | kmem_zone_free(xfs_log_item_desc_zone, lidp); | ||
1153 | } | ||
1154 | |||
1155 | /* | ||
1156 | * Unlink and free the given descriptor. | ||
1157 | */ | ||
1158 | void | ||
1159 | xfs_trans_del_item( | ||
1160 | struct xfs_log_item *lip) | ||
1161 | { | ||
1162 | xfs_trans_free_item_desc(lip->li_desc); | ||
1163 | lip->li_desc = NULL; | ||
1164 | } | ||
1165 | |||
1166 | /* | ||
1167 | * Unlock all of the items of a transaction and free all the descriptors | ||
1168 | * of that transaction. | ||
1169 | */ | ||
1170 | STATIC void | ||
1171 | xfs_trans_free_items( | ||
1172 | struct xfs_trans *tp, | ||
1173 | xfs_lsn_t commit_lsn, | ||
1174 | int flags) | ||
1175 | { | ||
1176 | struct xfs_log_item_desc *lidp, *next; | ||
1177 | |||
1178 | list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) { | ||
1179 | struct xfs_log_item *lip = lidp->lid_item; | ||
1180 | |||
1181 | lip->li_desc = NULL; | ||
1182 | |||
1183 | if (commit_lsn != NULLCOMMITLSN) | ||
1184 | IOP_COMMITTING(lip, commit_lsn); | ||
1185 | if (flags & XFS_TRANS_ABORT) | ||
1186 | lip->li_flags |= XFS_LI_ABORTED; | ||
1187 | IOP_UNLOCK(lip); | ||
1188 | |||
1189 | xfs_trans_free_item_desc(lidp); | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1193 | /* | ||
1194 | * Unlock the items associated with a transaction. | ||
1195 | * | ||
1196 | * Items which were not logged should be freed. Those which were logged must | ||
1197 | * still be tracked so they can be unpinned when the transaction commits. | ||
1198 | */ | ||
1199 | STATIC void | ||
1200 | xfs_trans_unlock_items( | ||
1201 | struct xfs_trans *tp, | ||
1202 | xfs_lsn_t commit_lsn) | ||
1203 | { | ||
1204 | struct xfs_log_item_desc *lidp, *next; | ||
1205 | |||
1206 | list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) { | ||
1207 | struct xfs_log_item *lip = lidp->lid_item; | ||
1208 | |||
1209 | lip->li_desc = NULL; | ||
1210 | |||
1211 | if (commit_lsn != NULLCOMMITLSN) | ||
1212 | IOP_COMMITTING(lip, commit_lsn); | ||
1213 | IOP_UNLOCK(lip); | ||
1214 | |||
1215 | /* | ||
1216 | * Free the descriptor if the item is not dirty | ||
1217 | * within this transaction. | ||
1218 | */ | ||
1219 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) | ||
1220 | xfs_trans_free_item_desc(lidp); | ||
1221 | } | ||
1222 | } | ||
1223 | |||
1224 | /* | ||
1127 | * Total up the number of log iovecs needed to commit this | 1225 | * Total up the number of log iovecs needed to commit this |
1128 | * transaction. The transaction itself needs one for the | 1226 | * transaction. The transaction itself needs one for the |
1129 | * transaction header. Ask each dirty item in turn how many | 1227 | * transaction header. Ask each dirty item in turn how many |
@@ -1134,30 +1232,27 @@ xfs_trans_count_vecs( | |||
1134 | struct xfs_trans *tp) | 1232 | struct xfs_trans *tp) |
1135 | { | 1233 | { |
1136 | int nvecs; | 1234 | int nvecs; |
1137 | xfs_log_item_desc_t *lidp; | 1235 | struct xfs_log_item_desc *lidp; |
1138 | 1236 | ||
1139 | nvecs = 1; | 1237 | nvecs = 1; |
1140 | lidp = xfs_trans_first_item(tp); | ||
1141 | ASSERT(lidp != NULL); | ||
1142 | 1238 | ||
1143 | /* In the non-debug case we need to start bailing out if we | 1239 | /* In the non-debug case we need to start bailing out if we |
1144 | * didn't find a log_item here, return zero and let trans_commit | 1240 | * didn't find a log_item here, return zero and let trans_commit |
1145 | * deal with it. | 1241 | * deal with it. |
1146 | */ | 1242 | */ |
1147 | if (lidp == NULL) | 1243 | if (list_empty(&tp->t_items)) { |
1244 | ASSERT(0); | ||
1148 | return 0; | 1245 | return 0; |
1246 | } | ||
1149 | 1247 | ||
1150 | while (lidp != NULL) { | 1248 | list_for_each_entry(lidp, &tp->t_items, lid_trans) { |
1151 | /* | 1249 | /* |
1152 | * Skip items which aren't dirty in this transaction. | 1250 | * Skip items which aren't dirty in this transaction. |
1153 | */ | 1251 | */ |
1154 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | 1252 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) |
1155 | lidp = xfs_trans_next_item(tp, lidp); | ||
1156 | continue; | 1253 | continue; |
1157 | } | ||
1158 | lidp->lid_size = IOP_SIZE(lidp->lid_item); | 1254 | lidp->lid_size = IOP_SIZE(lidp->lid_item); |
1159 | nvecs += lidp->lid_size; | 1255 | nvecs += lidp->lid_size; |
1160 | lidp = xfs_trans_next_item(tp, lidp); | ||
1161 | } | 1256 | } |
1162 | 1257 | ||
1163 | return nvecs; | 1258 | return nvecs; |
@@ -1177,7 +1272,7 @@ xfs_trans_fill_vecs( | |||
1177 | struct xfs_trans *tp, | 1272 | struct xfs_trans *tp, |
1178 | struct xfs_log_iovec *log_vector) | 1273 | struct xfs_log_iovec *log_vector) |
1179 | { | 1274 | { |
1180 | xfs_log_item_desc_t *lidp; | 1275 | struct xfs_log_item_desc *lidp; |
1181 | struct xfs_log_iovec *vecp; | 1276 | struct xfs_log_iovec *vecp; |
1182 | uint nitems; | 1277 | uint nitems; |
1183 | 1278 | ||
@@ -1188,14 +1283,11 @@ xfs_trans_fill_vecs( | |||
1188 | vecp = log_vector + 1; | 1283 | vecp = log_vector + 1; |
1189 | 1284 | ||
1190 | nitems = 0; | 1285 | nitems = 0; |
1191 | lidp = xfs_trans_first_item(tp); | 1286 | ASSERT(!list_empty(&tp->t_items)); |
1192 | ASSERT(lidp); | 1287 | list_for_each_entry(lidp, &tp->t_items, lid_trans) { |
1193 | while (lidp) { | ||
1194 | /* Skip items which aren't dirty in this transaction. */ | 1288 | /* Skip items which aren't dirty in this transaction. */ |
1195 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | 1289 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) |
1196 | lidp = xfs_trans_next_item(tp, lidp); | ||
1197 | continue; | 1290 | continue; |
1198 | } | ||
1199 | 1291 | ||
1200 | /* | 1292 | /* |
1201 | * The item may be marked dirty but not log anything. This can | 1293 | * The item may be marked dirty but not log anything. This can |
@@ -1206,7 +1298,6 @@ xfs_trans_fill_vecs( | |||
1206 | IOP_FORMAT(lidp->lid_item, vecp); | 1298 | IOP_FORMAT(lidp->lid_item, vecp); |
1207 | vecp += lidp->lid_size; | 1299 | vecp += lidp->lid_size; |
1208 | IOP_PIN(lidp->lid_item); | 1300 | IOP_PIN(lidp->lid_item); |
1209 | lidp = xfs_trans_next_item(tp, lidp); | ||
1210 | } | 1301 | } |
1211 | 1302 | ||
1212 | /* | 1303 | /* |
@@ -1284,7 +1375,7 @@ xfs_trans_item_committed( | |||
1284 | * log item flags, if anyone else stales the buffer we do not want to | 1375 | * log item flags, if anyone else stales the buffer we do not want to |
1285 | * pay any attention to it. | 1376 | * pay any attention to it. |
1286 | */ | 1377 | */ |
1287 | IOP_UNPIN(lip); | 1378 | IOP_UNPIN(lip, 0); |
1288 | } | 1379 | } |
1289 | 1380 | ||
1290 | /* | 1381 | /* |
@@ -1301,24 +1392,15 @@ xfs_trans_committed( | |||
1301 | struct xfs_trans *tp, | 1392 | struct xfs_trans *tp, |
1302 | int abortflag) | 1393 | int abortflag) |
1303 | { | 1394 | { |
1304 | xfs_log_item_desc_t *lidp; | 1395 | struct xfs_log_item_desc *lidp, *next; |
1305 | xfs_log_item_chunk_t *licp; | ||
1306 | xfs_log_item_chunk_t *next_licp; | ||
1307 | 1396 | ||
1308 | /* Call the transaction's completion callback if there is one. */ | 1397 | /* Call the transaction's completion callback if there is one. */ |
1309 | if (tp->t_callback != NULL) | 1398 | if (tp->t_callback != NULL) |
1310 | tp->t_callback(tp, tp->t_callarg); | 1399 | tp->t_callback(tp, tp->t_callarg); |
1311 | 1400 | ||
1312 | for (lidp = xfs_trans_first_item(tp); | 1401 | list_for_each_entry_safe(lidp, next, &tp->t_items, lid_trans) { |
1313 | lidp != NULL; | ||
1314 | lidp = xfs_trans_next_item(tp, lidp)) { | ||
1315 | xfs_trans_item_committed(lidp->lid_item, tp->t_lsn, abortflag); | 1402 | xfs_trans_item_committed(lidp->lid_item, tp->t_lsn, abortflag); |
1316 | } | 1403 | xfs_trans_free_item_desc(lidp); |
1317 | |||
1318 | /* free the item chunks, ignoring the embedded chunk */ | ||
1319 | for (licp = tp->t_items.lic_next; licp != NULL; licp = next_licp) { | ||
1320 | next_licp = licp->lic_next; | ||
1321 | kmem_free(licp); | ||
1322 | } | 1404 | } |
1323 | 1405 | ||
1324 | xfs_trans_free(tp); | 1406 | xfs_trans_free(tp); |
@@ -1333,16 +1415,14 @@ xfs_trans_uncommit( | |||
1333 | struct xfs_trans *tp, | 1415 | struct xfs_trans *tp, |
1334 | uint flags) | 1416 | uint flags) |
1335 | { | 1417 | { |
1336 | xfs_log_item_desc_t *lidp; | 1418 | struct xfs_log_item_desc *lidp; |
1337 | 1419 | ||
1338 | for (lidp = xfs_trans_first_item(tp); | 1420 | list_for_each_entry(lidp, &tp->t_items, lid_trans) { |
1339 | lidp != NULL; | ||
1340 | lidp = xfs_trans_next_item(tp, lidp)) { | ||
1341 | /* | 1421 | /* |
1342 | * Unpin all but those that aren't dirty. | 1422 | * Unpin all but those that aren't dirty. |
1343 | */ | 1423 | */ |
1344 | if (lidp->lid_flags & XFS_LID_DIRTY) | 1424 | if (lidp->lid_flags & XFS_LID_DIRTY) |
1345 | IOP_UNPIN_REMOVE(lidp->lid_item, tp); | 1425 | IOP_UNPIN(lidp->lid_item, 1); |
1346 | } | 1426 | } |
1347 | 1427 | ||
1348 | xfs_trans_unreserve_and_mod_sb(tp); | 1428 | xfs_trans_unreserve_and_mod_sb(tp); |
@@ -1508,33 +1588,28 @@ STATIC struct xfs_log_vec * | |||
1508 | xfs_trans_alloc_log_vecs( | 1588 | xfs_trans_alloc_log_vecs( |
1509 | xfs_trans_t *tp) | 1589 | xfs_trans_t *tp) |
1510 | { | 1590 | { |
1511 | xfs_log_item_desc_t *lidp; | 1591 | struct xfs_log_item_desc *lidp; |
1512 | struct xfs_log_vec *lv = NULL; | 1592 | struct xfs_log_vec *lv = NULL; |
1513 | struct xfs_log_vec *ret_lv = NULL; | 1593 | struct xfs_log_vec *ret_lv = NULL; |
1514 | 1594 | ||
1515 | lidp = xfs_trans_first_item(tp); | ||
1516 | 1595 | ||
1517 | /* Bail out if we didn't find a log item. */ | 1596 | /* Bail out if we didn't find a log item. */ |
1518 | if (!lidp) { | 1597 | if (list_empty(&tp->t_items)) { |
1519 | ASSERT(0); | 1598 | ASSERT(0); |
1520 | return NULL; | 1599 | return NULL; |
1521 | } | 1600 | } |
1522 | 1601 | ||
1523 | while (lidp != NULL) { | 1602 | list_for_each_entry(lidp, &tp->t_items, lid_trans) { |
1524 | struct xfs_log_vec *new_lv; | 1603 | struct xfs_log_vec *new_lv; |
1525 | 1604 | ||
1526 | /* Skip items which aren't dirty in this transaction. */ | 1605 | /* Skip items which aren't dirty in this transaction. */ |
1527 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) { | 1606 | if (!(lidp->lid_flags & XFS_LID_DIRTY)) |
1528 | lidp = xfs_trans_next_item(tp, lidp); | ||
1529 | continue; | 1607 | continue; |
1530 | } | ||
1531 | 1608 | ||
1532 | /* Skip items that do not have any vectors for writing */ | 1609 | /* Skip items that do not have any vectors for writing */ |
1533 | lidp->lid_size = IOP_SIZE(lidp->lid_item); | 1610 | lidp->lid_size = IOP_SIZE(lidp->lid_item); |
1534 | if (!lidp->lid_size) { | 1611 | if (!lidp->lid_size) |
1535 | lidp = xfs_trans_next_item(tp, lidp); | ||
1536 | continue; | 1612 | continue; |
1537 | } | ||
1538 | 1613 | ||
1539 | new_lv = kmem_zalloc(sizeof(*new_lv) + | 1614 | new_lv = kmem_zalloc(sizeof(*new_lv) + |
1540 | lidp->lid_size * sizeof(struct xfs_log_iovec), | 1615 | lidp->lid_size * sizeof(struct xfs_log_iovec), |
@@ -1549,7 +1624,6 @@ xfs_trans_alloc_log_vecs( | |||
1549 | else | 1624 | else |
1550 | lv->lv_next = new_lv; | 1625 | lv->lv_next = new_lv; |
1551 | lv = new_lv; | 1626 | lv = new_lv; |
1552 | lidp = xfs_trans_next_item(tp, lidp); | ||
1553 | } | 1627 | } |
1554 | 1628 | ||
1555 | return ret_lv; | 1629 | return ret_lv; |
@@ -1708,12 +1782,6 @@ xfs_trans_cancel( | |||
1708 | int flags) | 1782 | int flags) |
1709 | { | 1783 | { |
1710 | int log_flags; | 1784 | int log_flags; |
1711 | #ifdef DEBUG | ||
1712 | xfs_log_item_chunk_t *licp; | ||
1713 | xfs_log_item_desc_t *lidp; | ||
1714 | xfs_log_item_t *lip; | ||
1715 | int i; | ||
1716 | #endif | ||
1717 | xfs_mount_t *mp = tp->t_mountp; | 1785 | xfs_mount_t *mp = tp->t_mountp; |
1718 | 1786 | ||
1719 | /* | 1787 | /* |
@@ -1732,21 +1800,11 @@ xfs_trans_cancel( | |||
1732 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | 1800 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); |
1733 | } | 1801 | } |
1734 | #ifdef DEBUG | 1802 | #ifdef DEBUG |
1735 | if (!(flags & XFS_TRANS_ABORT)) { | 1803 | if (!(flags & XFS_TRANS_ABORT) && !XFS_FORCED_SHUTDOWN(mp)) { |
1736 | licp = &(tp->t_items); | 1804 | struct xfs_log_item_desc *lidp; |
1737 | while (licp != NULL) { | 1805 | |
1738 | lidp = licp->lic_descs; | 1806 | list_for_each_entry(lidp, &tp->t_items, lid_trans) |
1739 | for (i = 0; i < licp->lic_unused; i++, lidp++) { | 1807 | ASSERT(!(lidp->lid_item->li_type == XFS_LI_EFD)); |
1740 | if (xfs_lic_isfree(licp, i)) { | ||
1741 | continue; | ||
1742 | } | ||
1743 | |||
1744 | lip = lidp->lid_item; | ||
1745 | if (!XFS_FORCED_SHUTDOWN(mp)) | ||
1746 | ASSERT(!(lip->li_type == XFS_LI_EFD)); | ||
1747 | } | ||
1748 | licp = licp->lic_next; | ||
1749 | } | ||
1750 | } | 1808 | } |
1751 | #endif | 1809 | #endif |
1752 | xfs_trans_unreserve_and_mod_sb(tp); | 1810 | xfs_trans_unreserve_and_mod_sb(tp); |
@@ -1834,7 +1892,6 @@ xfs_trans_roll( | |||
1834 | if (error) | 1892 | if (error) |
1835 | return error; | 1893 | return error; |
1836 | 1894 | ||
1837 | xfs_trans_ijoin(trans, dp, XFS_ILOCK_EXCL); | 1895 | xfs_trans_ijoin(trans, dp); |
1838 | xfs_trans_ihold(trans, dp); | ||
1839 | return 0; | 1896 | return 0; |
1840 | } | 1897 | } |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index e639e8e9a2a9..c13c0f97b494 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -161,105 +161,14 @@ typedef struct xfs_trans_header { | |||
161 | * the amount of space needed to log the item it describes | 161 | * the amount of space needed to log the item it describes |
162 | * once we get to commit processing (see xfs_trans_commit()). | 162 | * once we get to commit processing (see xfs_trans_commit()). |
163 | */ | 163 | */ |
164 | typedef struct xfs_log_item_desc { | 164 | struct xfs_log_item_desc { |
165 | struct xfs_log_item *lid_item; | 165 | struct xfs_log_item *lid_item; |
166 | ushort lid_size; | 166 | ushort lid_size; |
167 | unsigned char lid_flags; | 167 | unsigned char lid_flags; |
168 | unsigned char lid_index; | 168 | struct list_head lid_trans; |
169 | } xfs_log_item_desc_t; | 169 | }; |
170 | 170 | ||
171 | #define XFS_LID_DIRTY 0x1 | 171 | #define XFS_LID_DIRTY 0x1 |
172 | #define XFS_LID_PINNED 0x2 | ||
173 | |||
174 | /* | ||
175 | * This structure is used to maintain a chunk list of log_item_desc | ||
176 | * structures. The free field is a bitmask indicating which descriptors | ||
177 | * in this chunk's array are free. The unused field is the first value | ||
178 | * not used since this chunk was allocated. | ||
179 | */ | ||
180 | #define XFS_LIC_NUM_SLOTS 15 | ||
181 | typedef struct xfs_log_item_chunk { | ||
182 | struct xfs_log_item_chunk *lic_next; | ||
183 | ushort lic_free; | ||
184 | ushort lic_unused; | ||
185 | xfs_log_item_desc_t lic_descs[XFS_LIC_NUM_SLOTS]; | ||
186 | } xfs_log_item_chunk_t; | ||
187 | |||
188 | #define XFS_LIC_MAX_SLOT (XFS_LIC_NUM_SLOTS - 1) | ||
189 | #define XFS_LIC_FREEMASK ((1 << XFS_LIC_NUM_SLOTS) - 1) | ||
190 | |||
191 | |||
192 | /* | ||
193 | * Initialize the given chunk. Set the chunk's free descriptor mask | ||
194 | * to indicate that all descriptors are free. The caller gets to set | ||
195 | * lic_unused to the right value (0 matches all free). The | ||
196 | * lic_descs.lid_index values are set up as each desc is allocated. | ||
197 | */ | ||
198 | static inline void xfs_lic_init(xfs_log_item_chunk_t *cp) | ||
199 | { | ||
200 | cp->lic_free = XFS_LIC_FREEMASK; | ||
201 | } | ||
202 | |||
203 | static inline void xfs_lic_init_slot(xfs_log_item_chunk_t *cp, int slot) | ||
204 | { | ||
205 | cp->lic_descs[slot].lid_index = (unsigned char)(slot); | ||
206 | } | ||
207 | |||
208 | static inline int xfs_lic_vacancy(xfs_log_item_chunk_t *cp) | ||
209 | { | ||
210 | return cp->lic_free & XFS_LIC_FREEMASK; | ||
211 | } | ||
212 | |||
213 | static inline void xfs_lic_all_free(xfs_log_item_chunk_t *cp) | ||
214 | { | ||
215 | cp->lic_free = XFS_LIC_FREEMASK; | ||
216 | } | ||
217 | |||
218 | static inline int xfs_lic_are_all_free(xfs_log_item_chunk_t *cp) | ||
219 | { | ||
220 | return ((cp->lic_free & XFS_LIC_FREEMASK) == XFS_LIC_FREEMASK); | ||
221 | } | ||
222 | |||
223 | static inline int xfs_lic_isfree(xfs_log_item_chunk_t *cp, int slot) | ||
224 | { | ||
225 | return (cp->lic_free & (1 << slot)); | ||
226 | } | ||
227 | |||
228 | static inline void xfs_lic_claim(xfs_log_item_chunk_t *cp, int slot) | ||
229 | { | ||
230 | cp->lic_free &= ~(1 << slot); | ||
231 | } | ||
232 | |||
233 | static inline void xfs_lic_relse(xfs_log_item_chunk_t *cp, int slot) | ||
234 | { | ||
235 | cp->lic_free |= 1 << slot; | ||
236 | } | ||
237 | |||
238 | static inline xfs_log_item_desc_t * | ||
239 | xfs_lic_slot(xfs_log_item_chunk_t *cp, int slot) | ||
240 | { | ||
241 | return &(cp->lic_descs[slot]); | ||
242 | } | ||
243 | |||
244 | static inline int xfs_lic_desc_to_slot(xfs_log_item_desc_t *dp) | ||
245 | { | ||
246 | return (uint)dp->lid_index; | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | * Calculate the address of a chunk given a descriptor pointer: | ||
251 | * dp - dp->lid_index give the address of the start of the lic_descs array. | ||
252 | * From this we subtract the offset of the lic_descs field in a chunk. | ||
253 | * All of this yields the address of the chunk, which is | ||
254 | * cast to a chunk pointer. | ||
255 | */ | ||
256 | static inline xfs_log_item_chunk_t * | ||
257 | xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) | ||
258 | { | ||
259 | return (xfs_log_item_chunk_t*) \ | ||
260 | (((xfs_caddr_t)((dp) - (dp)->lid_index)) - \ | ||
261 | (xfs_caddr_t)(((xfs_log_item_chunk_t*)0)->lic_descs)); | ||
262 | } | ||
263 | 172 | ||
264 | #define XFS_TRANS_MAGIC 0x5452414E /* 'TRAN' */ | 173 | #define XFS_TRANS_MAGIC 0x5452414E /* 'TRAN' */ |
265 | /* | 174 | /* |
@@ -275,8 +184,6 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) | |||
275 | /* | 184 | /* |
276 | * Values for call flags parameter. | 185 | * Values for call flags parameter. |
277 | */ | 186 | */ |
278 | #define XFS_TRANS_NOSLEEP 0x1 | ||
279 | #define XFS_TRANS_WAIT 0x2 | ||
280 | #define XFS_TRANS_RELEASE_LOG_RES 0x4 | 187 | #define XFS_TRANS_RELEASE_LOG_RES 0x4 |
281 | #define XFS_TRANS_ABORT 0x8 | 188 | #define XFS_TRANS_ABORT 0x8 |
282 | 189 | ||
@@ -438,8 +345,7 @@ typedef struct xfs_item_ops { | |||
438 | uint (*iop_size)(xfs_log_item_t *); | 345 | uint (*iop_size)(xfs_log_item_t *); |
439 | void (*iop_format)(xfs_log_item_t *, struct xfs_log_iovec *); | 346 | void (*iop_format)(xfs_log_item_t *, struct xfs_log_iovec *); |
440 | void (*iop_pin)(xfs_log_item_t *); | 347 | void (*iop_pin)(xfs_log_item_t *); |
441 | void (*iop_unpin)(xfs_log_item_t *); | 348 | void (*iop_unpin)(xfs_log_item_t *, int remove); |
442 | void (*iop_unpin_remove)(xfs_log_item_t *, struct xfs_trans *); | ||
443 | uint (*iop_trylock)(xfs_log_item_t *); | 349 | uint (*iop_trylock)(xfs_log_item_t *); |
444 | void (*iop_unlock)(xfs_log_item_t *); | 350 | void (*iop_unlock)(xfs_log_item_t *); |
445 | xfs_lsn_t (*iop_committed)(xfs_log_item_t *, xfs_lsn_t); | 351 | xfs_lsn_t (*iop_committed)(xfs_log_item_t *, xfs_lsn_t); |
@@ -451,8 +357,7 @@ typedef struct xfs_item_ops { | |||
451 | #define IOP_SIZE(ip) (*(ip)->li_ops->iop_size)(ip) | 357 | #define IOP_SIZE(ip) (*(ip)->li_ops->iop_size)(ip) |
452 | #define IOP_FORMAT(ip,vp) (*(ip)->li_ops->iop_format)(ip, vp) | 358 | #define IOP_FORMAT(ip,vp) (*(ip)->li_ops->iop_format)(ip, vp) |
453 | #define IOP_PIN(ip) (*(ip)->li_ops->iop_pin)(ip) | 359 | #define IOP_PIN(ip) (*(ip)->li_ops->iop_pin)(ip) |
454 | #define IOP_UNPIN(ip) (*(ip)->li_ops->iop_unpin)(ip) | 360 | #define IOP_UNPIN(ip, remove) (*(ip)->li_ops->iop_unpin)(ip, remove) |
455 | #define IOP_UNPIN_REMOVE(ip,tp) (*(ip)->li_ops->iop_unpin_remove)(ip, tp) | ||
456 | #define IOP_TRYLOCK(ip) (*(ip)->li_ops->iop_trylock)(ip) | 361 | #define IOP_TRYLOCK(ip) (*(ip)->li_ops->iop_trylock)(ip) |
457 | #define IOP_UNLOCK(ip) (*(ip)->li_ops->iop_unlock)(ip) | 362 | #define IOP_UNLOCK(ip) (*(ip)->li_ops->iop_unlock)(ip) |
458 | #define IOP_COMMITTED(ip, lsn) (*(ip)->li_ops->iop_committed)(ip, lsn) | 363 | #define IOP_COMMITTED(ip, lsn) (*(ip)->li_ops->iop_committed)(ip, lsn) |
@@ -516,8 +421,7 @@ typedef struct xfs_trans { | |||
516 | int64_t t_rblocks_delta;/* superblock rblocks change */ | 421 | int64_t t_rblocks_delta;/* superblock rblocks change */ |
517 | int64_t t_rextents_delta;/* superblocks rextents chg */ | 422 | int64_t t_rextents_delta;/* superblocks rextents chg */ |
518 | int64_t t_rextslog_delta;/* superblocks rextslog chg */ | 423 | int64_t t_rextslog_delta;/* superblocks rextslog chg */ |
519 | unsigned int t_items_free; /* log item descs free */ | 424 | struct list_head t_items; /* log item descriptors */ |
520 | xfs_log_item_chunk_t t_items; /* first log item desc chunk */ | ||
521 | xfs_trans_header_t t_header; /* header for in-log trans */ | 425 | xfs_trans_header_t t_header; /* header for in-log trans */ |
522 | struct list_head t_busy; /* list of busy extents */ | 426 | struct list_head t_busy; /* list of busy extents */ |
523 | unsigned long t_pflags; /* saved process flags state */ | 427 | unsigned long t_pflags; /* saved process flags state */ |
@@ -569,8 +473,8 @@ void xfs_trans_dquot_buf(xfs_trans_t *, struct xfs_buf *, uint); | |||
569 | void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); | 473 | void xfs_trans_inode_alloc_buf(xfs_trans_t *, struct xfs_buf *); |
570 | int xfs_trans_iget(struct xfs_mount *, xfs_trans_t *, | 474 | int xfs_trans_iget(struct xfs_mount *, xfs_trans_t *, |
571 | xfs_ino_t , uint, uint, struct xfs_inode **); | 475 | xfs_ino_t , uint, uint, struct xfs_inode **); |
572 | void xfs_trans_ijoin(xfs_trans_t *, struct xfs_inode *, uint); | 476 | void xfs_trans_ijoin_ref(struct xfs_trans *, struct xfs_inode *, uint); |
573 | void xfs_trans_ihold(xfs_trans_t *, struct xfs_inode *); | 477 | void xfs_trans_ijoin(struct xfs_trans *, struct xfs_inode *); |
574 | void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint); | 478 | void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint); |
575 | void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint); | 479 | void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint); |
576 | struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint); | 480 | struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint); |
@@ -595,6 +499,7 @@ int xfs_trans_ail_init(struct xfs_mount *); | |||
595 | void xfs_trans_ail_destroy(struct xfs_mount *); | 499 | void xfs_trans_ail_destroy(struct xfs_mount *); |
596 | 500 | ||
597 | extern kmem_zone_t *xfs_trans_zone; | 501 | extern kmem_zone_t *xfs_trans_zone; |
502 | extern kmem_zone_t *xfs_log_item_desc_zone; | ||
598 | 503 | ||
599 | #endif /* __KERNEL__ */ | 504 | #endif /* __KERNEL__ */ |
600 | 505 | ||
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index e799824f7245..dc9069568ff7 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_trans_priv.h" | 28 | #include "xfs_trans_priv.h" |
30 | #include "xfs_error.h" | 29 | #include "xfs_error.h" |
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index 63d81a22f4fd..90af025e6839 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
@@ -24,14 +24,10 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
37 | #include "xfs_buf_item.h" | 33 | #include "xfs_buf_item.h" |
@@ -51,36 +47,17 @@ xfs_trans_buf_item_match( | |||
51 | xfs_daddr_t blkno, | 47 | xfs_daddr_t blkno, |
52 | int len) | 48 | int len) |
53 | { | 49 | { |
54 | xfs_log_item_chunk_t *licp; | 50 | struct xfs_log_item_desc *lidp; |
55 | xfs_log_item_desc_t *lidp; | 51 | struct xfs_buf_log_item *blip; |
56 | xfs_buf_log_item_t *blip; | ||
57 | int i; | ||
58 | 52 | ||
59 | len = BBTOB(len); | 53 | len = BBTOB(len); |
60 | for (licp = &tp->t_items; licp != NULL; licp = licp->lic_next) { | 54 | list_for_each_entry(lidp, &tp->t_items, lid_trans) { |
61 | if (xfs_lic_are_all_free(licp)) { | 55 | blip = (struct xfs_buf_log_item *)lidp->lid_item; |
62 | ASSERT(licp == &tp->t_items); | 56 | if (blip->bli_item.li_type == XFS_LI_BUF && |
63 | ASSERT(licp->lic_next == NULL); | 57 | XFS_BUF_TARGET(blip->bli_buf) == target && |
64 | return NULL; | 58 | XFS_BUF_ADDR(blip->bli_buf) == blkno && |
65 | } | 59 | XFS_BUF_COUNT(blip->bli_buf) == len) |
66 | 60 | return blip->bli_buf; | |
67 | for (i = 0; i < licp->lic_unused; i++) { | ||
68 | /* | ||
69 | * Skip unoccupied slots. | ||
70 | */ | ||
71 | if (xfs_lic_isfree(licp, i)) | ||
72 | continue; | ||
73 | |||
74 | lidp = xfs_lic_slot(licp, i); | ||
75 | blip = (xfs_buf_log_item_t *)lidp->lid_item; | ||
76 | if (blip->bli_item.li_type != XFS_LI_BUF) | ||
77 | continue; | ||
78 | |||
79 | if (XFS_BUF_TARGET(blip->bli_buf) == target && | ||
80 | XFS_BUF_ADDR(blip->bli_buf) == blkno && | ||
81 | XFS_BUF_COUNT(blip->bli_buf) == len) | ||
82 | return blip->bli_buf; | ||
83 | } | ||
84 | } | 61 | } |
85 | 62 | ||
86 | return NULL; | 63 | return NULL; |
@@ -127,7 +104,7 @@ _xfs_trans_bjoin( | |||
127 | /* | 104 | /* |
128 | * Get a log_item_desc to point at the new item. | 105 | * Get a log_item_desc to point at the new item. |
129 | */ | 106 | */ |
130 | (void) xfs_trans_add_item(tp, (xfs_log_item_t *)bip); | 107 | xfs_trans_add_item(tp, &bip->bli_item); |
131 | 108 | ||
132 | /* | 109 | /* |
133 | * Initialize b_fsprivate2 so we can find it with incore_match() | 110 | * Initialize b_fsprivate2 so we can find it with incore_match() |
@@ -483,7 +460,6 @@ xfs_trans_brelse(xfs_trans_t *tp, | |||
483 | { | 460 | { |
484 | xfs_buf_log_item_t *bip; | 461 | xfs_buf_log_item_t *bip; |
485 | xfs_log_item_t *lip; | 462 | xfs_log_item_t *lip; |
486 | xfs_log_item_desc_t *lidp; | ||
487 | 463 | ||
488 | /* | 464 | /* |
489 | * Default to a normal brelse() call if the tp is NULL. | 465 | * Default to a normal brelse() call if the tp is NULL. |
@@ -514,13 +490,6 @@ xfs_trans_brelse(xfs_trans_t *tp, | |||
514 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL)); | 490 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL)); |
515 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 491 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
516 | 492 | ||
517 | /* | ||
518 | * Find the item descriptor pointing to this buffer's | ||
519 | * log item. It must be there. | ||
520 | */ | ||
521 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip); | ||
522 | ASSERT(lidp != NULL); | ||
523 | |||
524 | trace_xfs_trans_brelse(bip); | 493 | trace_xfs_trans_brelse(bip); |
525 | 494 | ||
526 | /* | 495 | /* |
@@ -536,7 +505,7 @@ xfs_trans_brelse(xfs_trans_t *tp, | |||
536 | * If the buffer is dirty within this transaction, we can't | 505 | * If the buffer is dirty within this transaction, we can't |
537 | * release it until we commit. | 506 | * release it until we commit. |
538 | */ | 507 | */ |
539 | if (lidp->lid_flags & XFS_LID_DIRTY) | 508 | if (bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY) |
540 | return; | 509 | return; |
541 | 510 | ||
542 | /* | 511 | /* |
@@ -553,7 +522,7 @@ xfs_trans_brelse(xfs_trans_t *tp, | |||
553 | /* | 522 | /* |
554 | * Free up the log item descriptor tracking the released item. | 523 | * Free up the log item descriptor tracking the released item. |
555 | */ | 524 | */ |
556 | xfs_trans_free_item(tp, lidp); | 525 | xfs_trans_del_item(&bip->bli_item); |
557 | 526 | ||
558 | /* | 527 | /* |
559 | * Clear the hold flag in the buf log item if it is set. | 528 | * Clear the hold flag in the buf log item if it is set. |
@@ -665,7 +634,6 @@ xfs_trans_log_buf(xfs_trans_t *tp, | |||
665 | uint last) | 634 | uint last) |
666 | { | 635 | { |
667 | xfs_buf_log_item_t *bip; | 636 | xfs_buf_log_item_t *bip; |
668 | xfs_log_item_desc_t *lidp; | ||
669 | 637 | ||
670 | ASSERT(XFS_BUF_ISBUSY(bp)); | 638 | ASSERT(XFS_BUF_ISBUSY(bp)); |
671 | ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); | 639 | ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); |
@@ -690,7 +658,7 @@ xfs_trans_log_buf(xfs_trans_t *tp, | |||
690 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | 658 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); |
691 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 659 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
692 | XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks); | 660 | XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks); |
693 | bip->bli_item.li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*))xfs_buf_iodone; | 661 | bip->bli_item.li_cb = xfs_buf_iodone; |
694 | 662 | ||
695 | trace_xfs_trans_log_buf(bip); | 663 | trace_xfs_trans_log_buf(bip); |
696 | 664 | ||
@@ -707,11 +675,8 @@ xfs_trans_log_buf(xfs_trans_t *tp, | |||
707 | bip->bli_format.blf_flags &= ~XFS_BLF_CANCEL; | 675 | bip->bli_format.blf_flags &= ~XFS_BLF_CANCEL; |
708 | } | 676 | } |
709 | 677 | ||
710 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip); | ||
711 | ASSERT(lidp != NULL); | ||
712 | |||
713 | tp->t_flags |= XFS_TRANS_DIRTY; | 678 | tp->t_flags |= XFS_TRANS_DIRTY; |
714 | lidp->lid_flags |= XFS_LID_DIRTY; | 679 | bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; |
715 | bip->bli_flags |= XFS_BLI_LOGGED; | 680 | bip->bli_flags |= XFS_BLI_LOGGED; |
716 | xfs_buf_item_log(bip, first, last); | 681 | xfs_buf_item_log(bip, first, last); |
717 | } | 682 | } |
@@ -740,7 +705,6 @@ xfs_trans_binval( | |||
740 | xfs_trans_t *tp, | 705 | xfs_trans_t *tp, |
741 | xfs_buf_t *bp) | 706 | xfs_buf_t *bp) |
742 | { | 707 | { |
743 | xfs_log_item_desc_t *lidp; | ||
744 | xfs_buf_log_item_t *bip; | 708 | xfs_buf_log_item_t *bip; |
745 | 709 | ||
746 | ASSERT(XFS_BUF_ISBUSY(bp)); | 710 | ASSERT(XFS_BUF_ISBUSY(bp)); |
@@ -748,8 +712,6 @@ xfs_trans_binval( | |||
748 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); | 712 | ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); |
749 | 713 | ||
750 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); | 714 | bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); |
751 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip); | ||
752 | ASSERT(lidp != NULL); | ||
753 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 715 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
754 | 716 | ||
755 | trace_xfs_trans_binval(bip); | 717 | trace_xfs_trans_binval(bip); |
@@ -764,7 +726,7 @@ xfs_trans_binval( | |||
764 | ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY))); | 726 | ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY))); |
765 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_INODE_BUF)); | 727 | ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_INODE_BUF)); |
766 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); | 728 | ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL); |
767 | ASSERT(lidp->lid_flags & XFS_LID_DIRTY); | 729 | ASSERT(bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY); |
768 | ASSERT(tp->t_flags & XFS_TRANS_DIRTY); | 730 | ASSERT(tp->t_flags & XFS_TRANS_DIRTY); |
769 | return; | 731 | return; |
770 | } | 732 | } |
@@ -797,7 +759,7 @@ xfs_trans_binval( | |||
797 | bip->bli_format.blf_flags |= XFS_BLF_CANCEL; | 759 | bip->bli_format.blf_flags |= XFS_BLF_CANCEL; |
798 | memset((char *)(bip->bli_format.blf_data_map), 0, | 760 | memset((char *)(bip->bli_format.blf_data_map), 0, |
799 | (bip->bli_format.blf_map_size * sizeof(uint))); | 761 | (bip->bli_format.blf_map_size * sizeof(uint))); |
800 | lidp->lid_flags |= XFS_LID_DIRTY; | 762 | bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; |
801 | tp->t_flags |= XFS_TRANS_DIRTY; | 763 | tp->t_flags |= XFS_TRANS_DIRTY; |
802 | } | 764 | } |
803 | 765 | ||
@@ -853,12 +815,9 @@ xfs_trans_stale_inode_buf( | |||
853 | ASSERT(atomic_read(&bip->bli_refcount) > 0); | 815 | ASSERT(atomic_read(&bip->bli_refcount) > 0); |
854 | 816 | ||
855 | bip->bli_flags |= XFS_BLI_STALE_INODE; | 817 | bip->bli_flags |= XFS_BLI_STALE_INODE; |
856 | bip->bli_item.li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) | 818 | bip->bli_item.li_cb = xfs_buf_iodone; |
857 | xfs_buf_iodone; | ||
858 | } | 819 | } |
859 | 820 | ||
860 | |||
861 | |||
862 | /* | 821 | /* |
863 | * Mark the buffer as being one which contains newly allocated | 822 | * Mark the buffer as being one which contains newly allocated |
864 | * inodes. We need to make sure that even if this buffer is | 823 | * inodes. We need to make sure that even if this buffer is |
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c index 27cce2a9c7e9..f783d5e9fa70 100644 --- a/fs/xfs/xfs_trans_extfree.c +++ b/fs/xfs/xfs_trans_extfree.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dmapi.h" | ||
27 | #include "xfs_mount.h" | 26 | #include "xfs_mount.h" |
28 | #include "xfs_trans_priv.h" | 27 | #include "xfs_trans_priv.h" |
29 | #include "xfs_extfree_item.h" | 28 | #include "xfs_extfree_item.h" |
@@ -49,9 +48,8 @@ xfs_trans_get_efi(xfs_trans_t *tp, | |||
49 | /* | 48 | /* |
50 | * Get a log_item_desc to point at the new item. | 49 | * Get a log_item_desc to point at the new item. |
51 | */ | 50 | */ |
52 | (void) xfs_trans_add_item(tp, (xfs_log_item_t*)efip); | 51 | xfs_trans_add_item(tp, &efip->efi_item); |
53 | 52 | return efip; | |
54 | return (efip); | ||
55 | } | 53 | } |
56 | 54 | ||
57 | /* | 55 | /* |
@@ -65,15 +63,11 @@ xfs_trans_log_efi_extent(xfs_trans_t *tp, | |||
65 | xfs_fsblock_t start_block, | 63 | xfs_fsblock_t start_block, |
66 | xfs_extlen_t ext_len) | 64 | xfs_extlen_t ext_len) |
67 | { | 65 | { |
68 | xfs_log_item_desc_t *lidp; | ||
69 | uint next_extent; | 66 | uint next_extent; |
70 | xfs_extent_t *extp; | 67 | xfs_extent_t *extp; |
71 | 68 | ||
72 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)efip); | ||
73 | ASSERT(lidp != NULL); | ||
74 | |||
75 | tp->t_flags |= XFS_TRANS_DIRTY; | 69 | tp->t_flags |= XFS_TRANS_DIRTY; |
76 | lidp->lid_flags |= XFS_LID_DIRTY; | 70 | efip->efi_item.li_desc->lid_flags |= XFS_LID_DIRTY; |
77 | 71 | ||
78 | next_extent = efip->efi_next_extent; | 72 | next_extent = efip->efi_next_extent; |
79 | ASSERT(next_extent < efip->efi_format.efi_nextents); | 73 | ASSERT(next_extent < efip->efi_format.efi_nextents); |
@@ -106,9 +100,8 @@ xfs_trans_get_efd(xfs_trans_t *tp, | |||
106 | /* | 100 | /* |
107 | * Get a log_item_desc to point at the new item. | 101 | * Get a log_item_desc to point at the new item. |
108 | */ | 102 | */ |
109 | (void) xfs_trans_add_item(tp, (xfs_log_item_t*)efdp); | 103 | xfs_trans_add_item(tp, &efdp->efd_item); |
110 | 104 | return efdp; | |
111 | return (efdp); | ||
112 | } | 105 | } |
113 | 106 | ||
114 | /* | 107 | /* |
@@ -122,15 +115,11 @@ xfs_trans_log_efd_extent(xfs_trans_t *tp, | |||
122 | xfs_fsblock_t start_block, | 115 | xfs_fsblock_t start_block, |
123 | xfs_extlen_t ext_len) | 116 | xfs_extlen_t ext_len) |
124 | { | 117 | { |
125 | xfs_log_item_desc_t *lidp; | ||
126 | uint next_extent; | 118 | uint next_extent; |
127 | xfs_extent_t *extp; | 119 | xfs_extent_t *extp; |
128 | 120 | ||
129 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)efdp); | ||
130 | ASSERT(lidp != NULL); | ||
131 | |||
132 | tp->t_flags |= XFS_TRANS_DIRTY; | 121 | tp->t_flags |= XFS_TRANS_DIRTY; |
133 | lidp->lid_flags |= XFS_LID_DIRTY; | 122 | efdp->efd_item.li_desc->lid_flags |= XFS_LID_DIRTY; |
134 | 123 | ||
135 | next_extent = efdp->efd_next_extent; | 124 | next_extent = efdp->efd_next_extent; |
136 | ASSERT(next_extent < efdp->efd_format.efd_nextents); | 125 | ASSERT(next_extent < efdp->efd_format.efd_nextents); |
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index 2559dfec946b..cdc53a1050c5 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c | |||
@@ -24,20 +24,16 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | ||
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir2_sf.h" | ||
34 | #include "xfs_attr_sf.h" | ||
35 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 32 | #include "xfs_inode.h" |
37 | #include "xfs_btree.h" | 33 | #include "xfs_btree.h" |
38 | #include "xfs_ialloc.h" | ||
39 | #include "xfs_trans_priv.h" | 34 | #include "xfs_trans_priv.h" |
40 | #include "xfs_inode_item.h" | 35 | #include "xfs_inode_item.h" |
36 | #include "xfs_trace.h" | ||
41 | 37 | ||
42 | #ifdef XFS_TRANS_DEBUG | 38 | #ifdef XFS_TRANS_DEBUG |
43 | STATIC void | 39 | STATIC void |
@@ -47,7 +43,6 @@ xfs_trans_inode_broot_debug( | |||
47 | #define xfs_trans_inode_broot_debug(ip) | 43 | #define xfs_trans_inode_broot_debug(ip) |
48 | #endif | 44 | #endif |
49 | 45 | ||
50 | |||
51 | /* | 46 | /* |
52 | * Get an inode and join it to the transaction. | 47 | * Get an inode and join it to the transaction. |
53 | */ | 48 | */ |
@@ -63,77 +58,65 @@ xfs_trans_iget( | |||
63 | int error; | 58 | int error; |
64 | 59 | ||
65 | error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp); | 60 | error = xfs_iget(mp, tp, ino, flags, lock_flags, ipp); |
66 | if (!error && tp) | 61 | if (!error && tp) { |
67 | xfs_trans_ijoin(tp, *ipp, lock_flags); | 62 | xfs_trans_ijoin(tp, *ipp); |
63 | (*ipp)->i_itemp->ili_lock_flags = lock_flags; | ||
64 | } | ||
68 | return error; | 65 | return error; |
69 | } | 66 | } |
70 | 67 | ||
71 | /* | 68 | /* |
72 | * Add the locked inode to the transaction. | 69 | * Add a locked inode to the transaction. |
73 | * The inode must be locked, and it cannot be associated with any | 70 | * |
74 | * transaction. The caller must specify the locks already held | 71 | * The inode must be locked, and it cannot be associated with any transaction. |
75 | * on the inode. | ||
76 | */ | 72 | */ |
77 | void | 73 | void |
78 | xfs_trans_ijoin( | 74 | xfs_trans_ijoin( |
79 | xfs_trans_t *tp, | 75 | struct xfs_trans *tp, |
80 | xfs_inode_t *ip, | 76 | struct xfs_inode *ip) |
81 | uint lock_flags) | ||
82 | { | 77 | { |
83 | xfs_inode_log_item_t *iip; | 78 | xfs_inode_log_item_t *iip; |
84 | 79 | ||
85 | ASSERT(ip->i_transp == NULL); | 80 | ASSERT(ip->i_transp == NULL); |
86 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 81 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
87 | ASSERT(lock_flags & XFS_ILOCK_EXCL); | ||
88 | if (ip->i_itemp == NULL) | 82 | if (ip->i_itemp == NULL) |
89 | xfs_inode_item_init(ip, ip->i_mount); | 83 | xfs_inode_item_init(ip, ip->i_mount); |
90 | iip = ip->i_itemp; | 84 | iip = ip->i_itemp; |
91 | ASSERT(iip->ili_flags == 0); | 85 | ASSERT(iip->ili_lock_flags == 0); |
92 | 86 | ||
93 | /* | 87 | /* |
94 | * Get a log_item_desc to point at the new item. | 88 | * Get a log_item_desc to point at the new item. |
95 | */ | 89 | */ |
96 | (void) xfs_trans_add_item(tp, (xfs_log_item_t*)(iip)); | 90 | xfs_trans_add_item(tp, &iip->ili_item); |
97 | 91 | ||
98 | xfs_trans_inode_broot_debug(ip); | 92 | xfs_trans_inode_broot_debug(ip); |
99 | 93 | ||
100 | /* | 94 | /* |
101 | * If the IO lock is already held, mark that in the inode log item. | ||
102 | */ | ||
103 | if (lock_flags & XFS_IOLOCK_EXCL) { | ||
104 | iip->ili_flags |= XFS_ILI_IOLOCKED_EXCL; | ||
105 | } else if (lock_flags & XFS_IOLOCK_SHARED) { | ||
106 | iip->ili_flags |= XFS_ILI_IOLOCKED_SHARED; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * Initialize i_transp so we can find it with xfs_inode_incore() | 95 | * Initialize i_transp so we can find it with xfs_inode_incore() |
111 | * in xfs_trans_iget() above. | 96 | * in xfs_trans_iget() above. |
112 | */ | 97 | */ |
113 | ip->i_transp = tp; | 98 | ip->i_transp = tp; |
114 | } | 99 | } |
115 | 100 | ||
116 | |||
117 | |||
118 | /* | 101 | /* |
119 | * Mark the inode as not needing to be unlocked when the inode item's | 102 | * Add a locked inode to the transaction. |
120 | * IOP_UNLOCK() routine is called. The inode must already be locked | 103 | * |
121 | * and associated with the given transaction. | 104 | * |
105 | * Grabs a reference to the inode which will be dropped when the transaction | ||
106 | * is commited. The inode will also be unlocked at that point. The inode | ||
107 | * must be locked, and it cannot be associated with any transaction. | ||
122 | */ | 108 | */ |
123 | /*ARGSUSED*/ | ||
124 | void | 109 | void |
125 | xfs_trans_ihold( | 110 | xfs_trans_ijoin_ref( |
126 | xfs_trans_t *tp, | 111 | struct xfs_trans *tp, |
127 | xfs_inode_t *ip) | 112 | struct xfs_inode *ip, |
113 | uint lock_flags) | ||
128 | { | 114 | { |
129 | ASSERT(ip->i_transp == tp); | 115 | xfs_trans_ijoin(tp, ip); |
130 | ASSERT(ip->i_itemp != NULL); | 116 | IHOLD(ip); |
131 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 117 | ip->i_itemp->ili_lock_flags = lock_flags; |
132 | |||
133 | ip->i_itemp->ili_flags |= XFS_ILI_HOLD; | ||
134 | } | 118 | } |
135 | 119 | ||
136 | |||
137 | /* | 120 | /* |
138 | * This is called to mark the fields indicated in fieldmask as needing | 121 | * This is called to mark the fields indicated in fieldmask as needing |
139 | * to be logged when the transaction is committed. The inode must | 122 | * to be logged when the transaction is committed. The inode must |
@@ -149,17 +132,12 @@ xfs_trans_log_inode( | |||
149 | xfs_inode_t *ip, | 132 | xfs_inode_t *ip, |
150 | uint flags) | 133 | uint flags) |
151 | { | 134 | { |
152 | xfs_log_item_desc_t *lidp; | ||
153 | |||
154 | ASSERT(ip->i_transp == tp); | 135 | ASSERT(ip->i_transp == tp); |
155 | ASSERT(ip->i_itemp != NULL); | 136 | ASSERT(ip->i_itemp != NULL); |
156 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 137 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
157 | 138 | ||
158 | lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)(ip->i_itemp)); | ||
159 | ASSERT(lidp != NULL); | ||
160 | |||
161 | tp->t_flags |= XFS_TRANS_DIRTY; | 139 | tp->t_flags |= XFS_TRANS_DIRTY; |
162 | lidp->lid_flags |= XFS_LID_DIRTY; | 140 | ip->i_itemp->ili_item.li_desc->lid_flags |= XFS_LID_DIRTY; |
163 | 141 | ||
164 | /* | 142 | /* |
165 | * Always OR in the bits from the ili_last_fields field. | 143 | * Always OR in the bits from the ili_last_fields field. |
diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c deleted file mode 100644 index f11d37d06dcc..000000000000 --- a/fs/xfs/xfs_trans_item.c +++ /dev/null | |||
@@ -1,441 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #include "xfs.h" | ||
19 | #include "xfs_fs.h" | ||
20 | #include "xfs_types.h" | ||
21 | #include "xfs_log.h" | ||
22 | #include "xfs_inum.h" | ||
23 | #include "xfs_trans.h" | ||
24 | #include "xfs_trans_priv.h" | ||
25 | /* XXX: from here down needed until struct xfs_trans has its own ailp */ | ||
26 | #include "xfs_bit.h" | ||
27 | #include "xfs_buf_item.h" | ||
28 | #include "xfs_sb.h" | ||
29 | #include "xfs_ag.h" | ||
30 | #include "xfs_dir2.h" | ||
31 | #include "xfs_dmapi.h" | ||
32 | #include "xfs_mount.h" | ||
33 | |||
34 | STATIC int xfs_trans_unlock_chunk(xfs_log_item_chunk_t *, | ||
35 | int, int, xfs_lsn_t); | ||
36 | |||
37 | /* | ||
38 | * This is called to add the given log item to the transaction's | ||
39 | * list of log items. It must find a free log item descriptor | ||
40 | * or allocate a new one and add the item to that descriptor. | ||
41 | * The function returns a pointer to item descriptor used to point | ||
42 | * to the new item. The log item will now point to its new descriptor | ||
43 | * with its li_desc field. | ||
44 | */ | ||
45 | xfs_log_item_desc_t * | ||
46 | xfs_trans_add_item(xfs_trans_t *tp, xfs_log_item_t *lip) | ||
47 | { | ||
48 | xfs_log_item_desc_t *lidp; | ||
49 | xfs_log_item_chunk_t *licp; | ||
50 | int i=0; | ||
51 | |||
52 | /* | ||
53 | * If there are no free descriptors, allocate a new chunk | ||
54 | * of them and put it at the front of the chunk list. | ||
55 | */ | ||
56 | if (tp->t_items_free == 0) { | ||
57 | licp = (xfs_log_item_chunk_t*) | ||
58 | kmem_alloc(sizeof(xfs_log_item_chunk_t), KM_SLEEP); | ||
59 | ASSERT(licp != NULL); | ||
60 | /* | ||
61 | * Initialize the chunk, and then | ||
62 | * claim the first slot in the newly allocated chunk. | ||
63 | */ | ||
64 | xfs_lic_init(licp); | ||
65 | xfs_lic_claim(licp, 0); | ||
66 | licp->lic_unused = 1; | ||
67 | xfs_lic_init_slot(licp, 0); | ||
68 | lidp = xfs_lic_slot(licp, 0); | ||
69 | |||
70 | /* | ||
71 | * Link in the new chunk and update the free count. | ||
72 | */ | ||
73 | licp->lic_next = tp->t_items.lic_next; | ||
74 | tp->t_items.lic_next = licp; | ||
75 | tp->t_items_free = XFS_LIC_NUM_SLOTS - 1; | ||
76 | |||
77 | /* | ||
78 | * Initialize the descriptor and the generic portion | ||
79 | * of the log item. | ||
80 | * | ||
81 | * Point the new slot at this item and return it. | ||
82 | * Also point the log item at its currently active | ||
83 | * descriptor and set the item's mount pointer. | ||
84 | */ | ||
85 | lidp->lid_item = lip; | ||
86 | lidp->lid_flags = 0; | ||
87 | lidp->lid_size = 0; | ||
88 | lip->li_desc = lidp; | ||
89 | lip->li_mountp = tp->t_mountp; | ||
90 | lip->li_ailp = tp->t_mountp->m_ail; | ||
91 | return lidp; | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * Find the free descriptor. It is somewhere in the chunklist | ||
96 | * of descriptors. | ||
97 | */ | ||
98 | licp = &tp->t_items; | ||
99 | while (licp != NULL) { | ||
100 | if (xfs_lic_vacancy(licp)) { | ||
101 | if (licp->lic_unused <= XFS_LIC_MAX_SLOT) { | ||
102 | i = licp->lic_unused; | ||
103 | ASSERT(xfs_lic_isfree(licp, i)); | ||
104 | break; | ||
105 | } | ||
106 | for (i = 0; i <= XFS_LIC_MAX_SLOT; i++) { | ||
107 | if (xfs_lic_isfree(licp, i)) | ||
108 | break; | ||
109 | } | ||
110 | ASSERT(i <= XFS_LIC_MAX_SLOT); | ||
111 | break; | ||
112 | } | ||
113 | licp = licp->lic_next; | ||
114 | } | ||
115 | ASSERT(licp != NULL); | ||
116 | /* | ||
117 | * If we find a free descriptor, claim it, | ||
118 | * initialize it, and return it. | ||
119 | */ | ||
120 | xfs_lic_claim(licp, i); | ||
121 | if (licp->lic_unused <= i) { | ||
122 | licp->lic_unused = i + 1; | ||
123 | xfs_lic_init_slot(licp, i); | ||
124 | } | ||
125 | lidp = xfs_lic_slot(licp, i); | ||
126 | tp->t_items_free--; | ||
127 | lidp->lid_item = lip; | ||
128 | lidp->lid_flags = 0; | ||
129 | lidp->lid_size = 0; | ||
130 | lip->li_desc = lidp; | ||
131 | lip->li_mountp = tp->t_mountp; | ||
132 | lip->li_ailp = tp->t_mountp->m_ail; | ||
133 | return lidp; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * Free the given descriptor. | ||
138 | * | ||
139 | * This requires setting the bit in the chunk's free mask corresponding | ||
140 | * to the given slot. | ||
141 | */ | ||
142 | void | ||
143 | xfs_trans_free_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) | ||
144 | { | ||
145 | uint slot; | ||
146 | xfs_log_item_chunk_t *licp; | ||
147 | xfs_log_item_chunk_t **licpp; | ||
148 | |||
149 | slot = xfs_lic_desc_to_slot(lidp); | ||
150 | licp = xfs_lic_desc_to_chunk(lidp); | ||
151 | xfs_lic_relse(licp, slot); | ||
152 | lidp->lid_item->li_desc = NULL; | ||
153 | tp->t_items_free++; | ||
154 | |||
155 | /* | ||
156 | * If there are no more used items in the chunk and this is not | ||
157 | * the chunk embedded in the transaction structure, then free | ||
158 | * the chunk. First pull it from the chunk list and then | ||
159 | * free it back to the heap. We didn't bother with a doubly | ||
160 | * linked list here because the lists should be very short | ||
161 | * and this is not a performance path. It's better to save | ||
162 | * the memory of the extra pointer. | ||
163 | * | ||
164 | * Also decrement the transaction structure's count of free items | ||
165 | * by the number in a chunk since we are freeing an empty chunk. | ||
166 | */ | ||
167 | if (xfs_lic_are_all_free(licp) && (licp != &(tp->t_items))) { | ||
168 | licpp = &(tp->t_items.lic_next); | ||
169 | while (*licpp != licp) { | ||
170 | ASSERT(*licpp != NULL); | ||
171 | licpp = &((*licpp)->lic_next); | ||
172 | } | ||
173 | *licpp = licp->lic_next; | ||
174 | kmem_free(licp); | ||
175 | tp->t_items_free -= XFS_LIC_NUM_SLOTS; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * This is called to find the descriptor corresponding to the given | ||
181 | * log item. It returns a pointer to the descriptor. | ||
182 | * The log item MUST have a corresponding descriptor in the given | ||
183 | * transaction. This routine does not return NULL, it panics. | ||
184 | * | ||
185 | * The descriptor pointer is kept in the log item's li_desc field. | ||
186 | * Just return it. | ||
187 | */ | ||
188 | /*ARGSUSED*/ | ||
189 | xfs_log_item_desc_t * | ||
190 | xfs_trans_find_item(xfs_trans_t *tp, xfs_log_item_t *lip) | ||
191 | { | ||
192 | ASSERT(lip->li_desc != NULL); | ||
193 | |||
194 | return lip->li_desc; | ||
195 | } | ||
196 | |||
197 | |||
198 | /* | ||
199 | * Return a pointer to the first descriptor in the chunk list. | ||
200 | * This does not return NULL if there are none, it panics. | ||
201 | * | ||
202 | * The first descriptor must be in either the first or second chunk. | ||
203 | * This is because the only chunk allowed to be empty is the first. | ||
204 | * All others are freed when they become empty. | ||
205 | * | ||
206 | * At some point this and xfs_trans_next_item() should be optimized | ||
207 | * to quickly look at the mask to determine if there is anything to | ||
208 | * look at. | ||
209 | */ | ||
210 | xfs_log_item_desc_t * | ||
211 | xfs_trans_first_item(xfs_trans_t *tp) | ||
212 | { | ||
213 | xfs_log_item_chunk_t *licp; | ||
214 | int i; | ||
215 | |||
216 | licp = &tp->t_items; | ||
217 | /* | ||
218 | * If it's not in the first chunk, skip to the second. | ||
219 | */ | ||
220 | if (xfs_lic_are_all_free(licp)) { | ||
221 | licp = licp->lic_next; | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * Return the first non-free descriptor in the chunk. | ||
226 | */ | ||
227 | ASSERT(!xfs_lic_are_all_free(licp)); | ||
228 | for (i = 0; i < licp->lic_unused; i++) { | ||
229 | if (xfs_lic_isfree(licp, i)) { | ||
230 | continue; | ||
231 | } | ||
232 | |||
233 | return xfs_lic_slot(licp, i); | ||
234 | } | ||
235 | cmn_err(CE_WARN, "xfs_trans_first_item() -- no first item"); | ||
236 | return NULL; | ||
237 | } | ||
238 | |||
239 | |||
240 | /* | ||
241 | * Given a descriptor, return the next descriptor in the chunk list. | ||
242 | * This returns NULL if there are no more used descriptors in the list. | ||
243 | * | ||
244 | * We do this by first locating the chunk in which the descriptor resides, | ||
245 | * and then scanning forward in the chunk and the list for the next | ||
246 | * used descriptor. | ||
247 | */ | ||
248 | /*ARGSUSED*/ | ||
249 | xfs_log_item_desc_t * | ||
250 | xfs_trans_next_item(xfs_trans_t *tp, xfs_log_item_desc_t *lidp) | ||
251 | { | ||
252 | xfs_log_item_chunk_t *licp; | ||
253 | int i; | ||
254 | |||
255 | licp = xfs_lic_desc_to_chunk(lidp); | ||
256 | |||
257 | /* | ||
258 | * First search the rest of the chunk. The for loop keeps us | ||
259 | * from referencing things beyond the end of the chunk. | ||
260 | */ | ||
261 | for (i = (int)xfs_lic_desc_to_slot(lidp) + 1; i < licp->lic_unused; i++) { | ||
262 | if (xfs_lic_isfree(licp, i)) { | ||
263 | continue; | ||
264 | } | ||
265 | |||
266 | return xfs_lic_slot(licp, i); | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * Now search the next chunk. It must be there, because the | ||
271 | * next chunk would have been freed if it were empty. | ||
272 | * If there is no next chunk, return NULL. | ||
273 | */ | ||
274 | if (licp->lic_next == NULL) { | ||
275 | return NULL; | ||
276 | } | ||
277 | |||
278 | licp = licp->lic_next; | ||
279 | ASSERT(!xfs_lic_are_all_free(licp)); | ||
280 | for (i = 0; i < licp->lic_unused; i++) { | ||
281 | if (xfs_lic_isfree(licp, i)) { | ||
282 | continue; | ||
283 | } | ||
284 | |||
285 | return xfs_lic_slot(licp, i); | ||
286 | } | ||
287 | ASSERT(0); | ||
288 | /* NOTREACHED */ | ||
289 | return NULL; /* keep gcc quite */ | ||
290 | } | ||
291 | |||
292 | /* | ||
293 | * This is called to unlock all of the items of a transaction and to free | ||
294 | * all the descriptors of that transaction. | ||
295 | * | ||
296 | * It walks the list of descriptors and unlocks each item. It frees | ||
297 | * each chunk except that embedded in the transaction as it goes along. | ||
298 | */ | ||
299 | void | ||
300 | xfs_trans_free_items( | ||
301 | xfs_trans_t *tp, | ||
302 | xfs_lsn_t commit_lsn, | ||
303 | int flags) | ||
304 | { | ||
305 | xfs_log_item_chunk_t *licp; | ||
306 | xfs_log_item_chunk_t *next_licp; | ||
307 | int abort; | ||
308 | |||
309 | abort = flags & XFS_TRANS_ABORT; | ||
310 | licp = &tp->t_items; | ||
311 | /* | ||
312 | * Special case the embedded chunk so we don't free it below. | ||
313 | */ | ||
314 | if (!xfs_lic_are_all_free(licp)) { | ||
315 | (void) xfs_trans_unlock_chunk(licp, 1, abort, commit_lsn); | ||
316 | xfs_lic_all_free(licp); | ||
317 | licp->lic_unused = 0; | ||
318 | } | ||
319 | licp = licp->lic_next; | ||
320 | |||
321 | /* | ||
322 | * Unlock each item in each chunk and free the chunks. | ||
323 | */ | ||
324 | while (licp != NULL) { | ||
325 | ASSERT(!xfs_lic_are_all_free(licp)); | ||
326 | (void) xfs_trans_unlock_chunk(licp, 1, abort, commit_lsn); | ||
327 | next_licp = licp->lic_next; | ||
328 | kmem_free(licp); | ||
329 | licp = next_licp; | ||
330 | } | ||
331 | |||
332 | /* | ||
333 | * Reset the transaction structure's free item count. | ||
334 | */ | ||
335 | tp->t_items_free = XFS_LIC_NUM_SLOTS; | ||
336 | tp->t_items.lic_next = NULL; | ||
337 | } | ||
338 | |||
339 | |||
340 | |||
341 | /* | ||
342 | * This is called to unlock the items associated with a transaction. | ||
343 | * Items which were not logged should be freed. | ||
344 | * Those which were logged must still be tracked so they can be unpinned | ||
345 | * when the transaction commits. | ||
346 | */ | ||
347 | void | ||
348 | xfs_trans_unlock_items(xfs_trans_t *tp, xfs_lsn_t commit_lsn) | ||
349 | { | ||
350 | xfs_log_item_chunk_t *licp; | ||
351 | xfs_log_item_chunk_t *next_licp; | ||
352 | xfs_log_item_chunk_t **licpp; | ||
353 | int freed; | ||
354 | |||
355 | freed = 0; | ||
356 | licp = &tp->t_items; | ||
357 | |||
358 | /* | ||
359 | * Special case the embedded chunk so we don't free. | ||
360 | */ | ||
361 | if (!xfs_lic_are_all_free(licp)) { | ||
362 | freed = xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn); | ||
363 | } | ||
364 | licpp = &(tp->t_items.lic_next); | ||
365 | licp = licp->lic_next; | ||
366 | |||
367 | /* | ||
368 | * Unlock each item in each chunk, free non-dirty descriptors, | ||
369 | * and free empty chunks. | ||
370 | */ | ||
371 | while (licp != NULL) { | ||
372 | ASSERT(!xfs_lic_are_all_free(licp)); | ||
373 | freed += xfs_trans_unlock_chunk(licp, 0, 0, commit_lsn); | ||
374 | next_licp = licp->lic_next; | ||
375 | if (xfs_lic_are_all_free(licp)) { | ||
376 | *licpp = next_licp; | ||
377 | kmem_free(licp); | ||
378 | freed -= XFS_LIC_NUM_SLOTS; | ||
379 | } else { | ||
380 | licpp = &(licp->lic_next); | ||
381 | } | ||
382 | ASSERT(*licpp == next_licp); | ||
383 | licp = next_licp; | ||
384 | } | ||
385 | |||
386 | /* | ||
387 | * Fix the free descriptor count in the transaction. | ||
388 | */ | ||
389 | tp->t_items_free += freed; | ||
390 | } | ||
391 | |||
392 | /* | ||
393 | * Unlock each item pointed to by a descriptor in the given chunk. | ||
394 | * Stamp the commit lsn into each item if necessary. | ||
395 | * Free descriptors pointing to items which are not dirty if freeing_chunk | ||
396 | * is zero. If freeing_chunk is non-zero, then we need to unlock all | ||
397 | * items in the chunk. | ||
398 | * | ||
399 | * Return the number of descriptors freed. | ||
400 | */ | ||
401 | STATIC int | ||
402 | xfs_trans_unlock_chunk( | ||
403 | xfs_log_item_chunk_t *licp, | ||
404 | int freeing_chunk, | ||
405 | int abort, | ||
406 | xfs_lsn_t commit_lsn) | ||
407 | { | ||
408 | xfs_log_item_desc_t *lidp; | ||
409 | xfs_log_item_t *lip; | ||
410 | int i; | ||
411 | int freed; | ||
412 | |||
413 | freed = 0; | ||
414 | lidp = licp->lic_descs; | ||
415 | for (i = 0; i < licp->lic_unused; i++, lidp++) { | ||
416 | if (xfs_lic_isfree(licp, i)) { | ||
417 | continue; | ||
418 | } | ||
419 | lip = lidp->lid_item; | ||
420 | lip->li_desc = NULL; | ||
421 | |||
422 | if (commit_lsn != NULLCOMMITLSN) | ||
423 | IOP_COMMITTING(lip, commit_lsn); | ||
424 | if (abort) | ||
425 | lip->li_flags |= XFS_LI_ABORTED; | ||
426 | IOP_UNLOCK(lip); | ||
427 | |||
428 | /* | ||
429 | * Free the descriptor if the item is not dirty | ||
430 | * within this transaction and the caller is not | ||
431 | * going to just free the entire thing regardless. | ||
432 | */ | ||
433 | if (!(freeing_chunk) && | ||
434 | (!(lidp->lid_flags & XFS_LID_DIRTY) || abort)) { | ||
435 | xfs_lic_relse(licp, i); | ||
436 | freed++; | ||
437 | } | ||
438 | } | ||
439 | |||
440 | return freed; | ||
441 | } | ||
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h index c6e4f2c8de6e..e2d93d8ead7b 100644 --- a/fs/xfs/xfs_trans_priv.h +++ b/fs/xfs/xfs_trans_priv.h | |||
@@ -23,22 +23,8 @@ struct xfs_log_item_desc; | |||
23 | struct xfs_mount; | 23 | struct xfs_mount; |
24 | struct xfs_trans; | 24 | struct xfs_trans; |
25 | 25 | ||
26 | /* | 26 | void xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *); |
27 | * From xfs_trans_item.c | 27 | void xfs_trans_del_item(struct xfs_log_item *); |
28 | */ | ||
29 | struct xfs_log_item_desc *xfs_trans_add_item(struct xfs_trans *, | ||
30 | struct xfs_log_item *); | ||
31 | void xfs_trans_free_item(struct xfs_trans *, | ||
32 | struct xfs_log_item_desc *); | ||
33 | struct xfs_log_item_desc *xfs_trans_find_item(struct xfs_trans *, | ||
34 | struct xfs_log_item *); | ||
35 | struct xfs_log_item_desc *xfs_trans_first_item(struct xfs_trans *); | ||
36 | struct xfs_log_item_desc *xfs_trans_next_item(struct xfs_trans *, | ||
37 | struct xfs_log_item_desc *); | ||
38 | |||
39 | void xfs_trans_unlock_items(struct xfs_trans *tp, xfs_lsn_t commit_lsn); | ||
40 | void xfs_trans_free_items(struct xfs_trans *tp, xfs_lsn_t commit_lsn, | ||
41 | int flags); | ||
42 | 28 | ||
43 | void xfs_trans_item_committed(struct xfs_log_item *lip, | 29 | void xfs_trans_item_committed(struct xfs_log_item *lip, |
44 | xfs_lsn_t commit_lsn, int aborted); | 30 | xfs_lsn_t commit_lsn, int aborted); |
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 4d88616bde91..b7d5769d2df0 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c | |||
@@ -25,18 +25,14 @@ | |||
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | ||
29 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_dir2_sf.h" | ||
32 | #include "xfs_attr_sf.h" | ||
33 | #include "xfs_dinode.h" | 30 | #include "xfs_dinode.h" |
34 | #include "xfs_inode.h" | 31 | #include "xfs_inode.h" |
35 | #include "xfs_inode_item.h" | 32 | #include "xfs_inode_item.h" |
36 | #include "xfs_bmap.h" | 33 | #include "xfs_bmap.h" |
37 | #include "xfs_error.h" | 34 | #include "xfs_error.h" |
38 | #include "xfs_quota.h" | 35 | #include "xfs_quota.h" |
39 | #include "xfs_rw.h" | ||
40 | #include "xfs_itable.h" | 36 | #include "xfs_itable.h" |
41 | #include "xfs_utils.h" | 37 | #include "xfs_utils.h" |
42 | 38 | ||
@@ -324,86 +320,3 @@ xfs_bumplink( | |||
324 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 320 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
325 | return 0; | 321 | return 0; |
326 | } | 322 | } |
327 | |||
328 | /* | ||
329 | * Try to truncate the given file to 0 length. Currently called | ||
330 | * only out of xfs_remove when it has to truncate a file to free | ||
331 | * up space for the remove to proceed. | ||
332 | */ | ||
333 | int | ||
334 | xfs_truncate_file( | ||
335 | xfs_mount_t *mp, | ||
336 | xfs_inode_t *ip) | ||
337 | { | ||
338 | xfs_trans_t *tp; | ||
339 | int error; | ||
340 | |||
341 | #ifdef QUOTADEBUG | ||
342 | /* | ||
343 | * This is called to truncate the quotainodes too. | ||
344 | */ | ||
345 | if (XFS_IS_UQUOTA_ON(mp)) { | ||
346 | if (ip->i_ino != mp->m_sb.sb_uquotino) | ||
347 | ASSERT(ip->i_udquot); | ||
348 | } | ||
349 | if (XFS_IS_OQUOTA_ON(mp)) { | ||
350 | if (ip->i_ino != mp->m_sb.sb_gquotino) | ||
351 | ASSERT(ip->i_gdquot); | ||
352 | } | ||
353 | #endif | ||
354 | /* | ||
355 | * Make the call to xfs_itruncate_start before starting the | ||
356 | * transaction, because we cannot make the call while we're | ||
357 | * in a transaction. | ||
358 | */ | ||
359 | xfs_ilock(ip, XFS_IOLOCK_EXCL); | ||
360 | error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE, (xfs_fsize_t)0); | ||
361 | if (error) { | ||
362 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
363 | return error; | ||
364 | } | ||
365 | |||
366 | tp = xfs_trans_alloc(mp, XFS_TRANS_TRUNCATE_FILE); | ||
367 | if ((error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, | ||
368 | XFS_TRANS_PERM_LOG_RES, | ||
369 | XFS_ITRUNCATE_LOG_COUNT))) { | ||
370 | xfs_trans_cancel(tp, 0); | ||
371 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | ||
372 | return error; | ||
373 | } | ||
374 | |||
375 | /* | ||
376 | * Follow the normal truncate locking protocol. Since we | ||
377 | * hold the inode in the transaction, we know that its number | ||
378 | * of references will stay constant. | ||
379 | */ | ||
380 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
381 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
382 | xfs_trans_ihold(tp, ip); | ||
383 | /* | ||
384 | * Signal a sync xaction. The only case where that isn't | ||
385 | * the case is if we're truncating an already unlinked file | ||
386 | * on a wsync fs. In that case, we know the blocks can't | ||
387 | * reappear in the file because the links to file are | ||
388 | * permanently toast. Currently, we're always going to | ||
389 | * want a sync transaction because this code is being | ||
390 | * called from places where nlink is guaranteed to be 1 | ||
391 | * but I'm leaving the tests in to protect against future | ||
392 | * changes -- rcc. | ||
393 | */ | ||
394 | error = xfs_itruncate_finish(&tp, ip, (xfs_fsize_t)0, | ||
395 | XFS_DATA_FORK, | ||
396 | ((ip->i_d.di_nlink != 0 || | ||
397 | !(mp->m_flags & XFS_MOUNT_WSYNC)) | ||
398 | ? 1 : 0)); | ||
399 | if (error) { | ||
400 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | | ||
401 | XFS_TRANS_ABORT); | ||
402 | } else { | ||
403 | xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
404 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | ||
405 | } | ||
406 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
407 | |||
408 | return error; | ||
409 | } | ||
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h index ef321225d269..f55b9678264f 100644 --- a/fs/xfs/xfs_utils.h +++ b/fs/xfs/xfs_utils.h | |||
@@ -18,7 +18,6 @@ | |||
18 | #ifndef __XFS_UTILS_H__ | 18 | #ifndef __XFS_UTILS_H__ |
19 | #define __XFS_UTILS_H__ | 19 | #define __XFS_UTILS_H__ |
20 | 20 | ||
21 | extern int xfs_truncate_file(xfs_mount_t *, xfs_inode_t *); | ||
22 | extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, | 21 | extern int xfs_dir_ialloc(xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, |
23 | xfs_dev_t, cred_t *, prid_t, int, | 22 | xfs_dev_t, cred_t *, prid_t, int, |
24 | xfs_inode_t **, int *); | 23 | xfs_inode_t **, int *); |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index c1646838898f..3ac137dd531b 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -26,19 +26,14 @@ | |||
26 | #include "xfs_sb.h" | 26 | #include "xfs_sb.h" |
27 | #include "xfs_ag.h" | 27 | #include "xfs_ag.h" |
28 | #include "xfs_dir2.h" | 28 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | ||
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_da_btree.h" | 30 | #include "xfs_da_btree.h" |
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | ||
34 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir2_sf.h" | ||
36 | #include "xfs_attr_sf.h" | ||
37 | #include "xfs_dinode.h" | 33 | #include "xfs_dinode.h" |
38 | #include "xfs_inode.h" | 34 | #include "xfs_inode.h" |
39 | #include "xfs_inode_item.h" | 35 | #include "xfs_inode_item.h" |
40 | #include "xfs_itable.h" | 36 | #include "xfs_itable.h" |
41 | #include "xfs_btree.h" | ||
42 | #include "xfs_ialloc.h" | 37 | #include "xfs_ialloc.h" |
43 | #include "xfs_alloc.h" | 38 | #include "xfs_alloc.h" |
44 | #include "xfs_bmap.h" | 39 | #include "xfs_bmap.h" |
@@ -73,7 +68,7 @@ xfs_setattr( | |||
73 | struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; | 68 | struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; |
74 | int need_iolock = 1; | 69 | int need_iolock = 1; |
75 | 70 | ||
76 | xfs_itrace_entry(ip); | 71 | trace_xfs_setattr(ip); |
77 | 72 | ||
78 | if (mp->m_flags & XFS_MOUNT_RDONLY) | 73 | if (mp->m_flags & XFS_MOUNT_RDONLY) |
79 | return XFS_ERROR(EROFS); | 74 | return XFS_ERROR(EROFS); |
@@ -143,16 +138,6 @@ xfs_setattr( | |||
143 | goto error_return; | 138 | goto error_return; |
144 | } | 139 | } |
145 | } else { | 140 | } else { |
146 | if (DM_EVENT_ENABLED(ip, DM_EVENT_TRUNCATE) && | ||
147 | !(flags & XFS_ATTR_DMI)) { | ||
148 | int dmflags = AT_DELAY_FLAG(flags) | DM_SEM_FLAG_WR; | ||
149 | code = XFS_SEND_DATA(mp, DM_EVENT_TRUNCATE, ip, | ||
150 | iattr->ia_size, 0, dmflags, NULL); | ||
151 | if (code) { | ||
152 | lock_flags = 0; | ||
153 | goto error_return; | ||
154 | } | ||
155 | } | ||
156 | if (need_iolock) | 141 | if (need_iolock) |
157 | lock_flags |= XFS_IOLOCK_EXCL; | 142 | lock_flags |= XFS_IOLOCK_EXCL; |
158 | } | 143 | } |
@@ -283,8 +268,7 @@ xfs_setattr( | |||
283 | commit_flags = XFS_TRANS_RELEASE_LOG_RES; | 268 | commit_flags = XFS_TRANS_RELEASE_LOG_RES; |
284 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 269 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
285 | 270 | ||
286 | xfs_trans_ijoin(tp, ip, lock_flags); | 271 | xfs_trans_ijoin(tp, ip); |
287 | xfs_trans_ihold(tp, ip); | ||
288 | 272 | ||
289 | /* | 273 | /* |
290 | * Only change the c/mtime if we are changing the size | 274 | * Only change the c/mtime if we are changing the size |
@@ -334,8 +318,7 @@ xfs_setattr( | |||
334 | xfs_iflags_set(ip, XFS_ITRUNCATED); | 318 | xfs_iflags_set(ip, XFS_ITRUNCATED); |
335 | } | 319 | } |
336 | } else if (tp) { | 320 | } else if (tp) { |
337 | xfs_trans_ijoin(tp, ip, lock_flags); | 321 | xfs_trans_ijoin(tp, ip); |
338 | xfs_trans_ihold(tp, ip); | ||
339 | } | 322 | } |
340 | 323 | ||
341 | /* | 324 | /* |
@@ -470,17 +453,10 @@ xfs_setattr( | |||
470 | return XFS_ERROR(code); | 453 | return XFS_ERROR(code); |
471 | } | 454 | } |
472 | 455 | ||
473 | if (DM_EVENT_ENABLED(ip, DM_EVENT_ATTRIBUTE) && | ||
474 | !(flags & XFS_ATTR_DMI)) { | ||
475 | (void) XFS_SEND_NAMESP(mp, DM_EVENT_ATTRIBUTE, ip, DM_RIGHT_NULL, | ||
476 | NULL, DM_RIGHT_NULL, NULL, NULL, | ||
477 | 0, 0, AT_DELAY_FLAG(flags)); | ||
478 | } | ||
479 | return 0; | 456 | return 0; |
480 | 457 | ||
481 | abort_return: | 458 | abort_return: |
482 | commit_flags |= XFS_TRANS_ABORT; | 459 | commit_flags |= XFS_TRANS_ABORT; |
483 | /* FALLTHROUGH */ | ||
484 | error_return: | 460 | error_return: |
485 | xfs_qm_dqrele(udqp); | 461 | xfs_qm_dqrele(udqp); |
486 | xfs_qm_dqrele(gdqp); | 462 | xfs_qm_dqrele(gdqp); |
@@ -516,7 +492,7 @@ xfs_readlink_bmap( | |||
516 | int error = 0; | 492 | int error = 0; |
517 | 493 | ||
518 | error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), 0, NULL, 0, | 494 | error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), 0, NULL, 0, |
519 | mval, &nmaps, NULL, NULL); | 495 | mval, &nmaps, NULL); |
520 | if (error) | 496 | if (error) |
521 | goto out; | 497 | goto out; |
522 | 498 | ||
@@ -557,7 +533,7 @@ xfs_readlink( | |||
557 | int pathlen; | 533 | int pathlen; |
558 | int error = 0; | 534 | int error = 0; |
559 | 535 | ||
560 | xfs_itrace_entry(ip); | 536 | trace_xfs_readlink(ip); |
561 | 537 | ||
562 | if (XFS_FORCED_SHUTDOWN(mp)) | 538 | if (XFS_FORCED_SHUTDOWN(mp)) |
563 | return XFS_ERROR(EIO); | 539 | return XFS_ERROR(EIO); |
@@ -613,14 +589,14 @@ xfs_free_eofblocks( | |||
613 | */ | 589 | */ |
614 | end_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)ip->i_size)); | 590 | end_fsb = XFS_B_TO_FSB(mp, ((xfs_ufsize_t)ip->i_size)); |
615 | last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); | 591 | last_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)XFS_MAXIOFFSET(mp)); |
616 | map_len = last_fsb - end_fsb; | 592 | if (last_fsb <= end_fsb) |
617 | if (map_len <= 0) | ||
618 | return 0; | 593 | return 0; |
594 | map_len = last_fsb - end_fsb; | ||
619 | 595 | ||
620 | nimaps = 1; | 596 | nimaps = 1; |
621 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 597 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
622 | error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0, | 598 | error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0, |
623 | NULL, 0, &imap, &nimaps, NULL, NULL); | 599 | NULL, 0, &imap, &nimaps, NULL); |
624 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 600 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
625 | 601 | ||
626 | if (!error && (nimaps != 0) && | 602 | if (!error && (nimaps != 0) && |
@@ -675,10 +651,7 @@ xfs_free_eofblocks( | |||
675 | } | 651 | } |
676 | 652 | ||
677 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 653 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
678 | xfs_trans_ijoin(tp, ip, | 654 | xfs_trans_ijoin(tp, ip); |
679 | XFS_IOLOCK_EXCL | | ||
680 | XFS_ILOCK_EXCL); | ||
681 | xfs_trans_ihold(tp, ip); | ||
682 | 655 | ||
683 | error = xfs_itruncate_finish(&tp, ip, | 656 | error = xfs_itruncate_finish(&tp, ip, |
684 | ip->i_size, | 657 | ip->i_size, |
@@ -750,8 +723,7 @@ xfs_inactive_symlink_rmt( | |||
750 | xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | 723 | xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); |
751 | size = (int)ip->i_d.di_size; | 724 | size = (int)ip->i_d.di_size; |
752 | ip->i_d.di_size = 0; | 725 | ip->i_d.di_size = 0; |
753 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | 726 | xfs_trans_ijoin(tp, ip); |
754 | xfs_trans_ihold(tp, ip); | ||
755 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 727 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
756 | /* | 728 | /* |
757 | * Find the block(s) so we can inval and unmap them. | 729 | * Find the block(s) so we can inval and unmap them. |
@@ -761,7 +733,7 @@ xfs_inactive_symlink_rmt( | |||
761 | nmaps = ARRAY_SIZE(mval); | 733 | nmaps = ARRAY_SIZE(mval); |
762 | if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size), | 734 | if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size), |
763 | XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps, | 735 | XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps, |
764 | &free_list, NULL))) | 736 | &free_list))) |
765 | goto error0; | 737 | goto error0; |
766 | /* | 738 | /* |
767 | * Invalidate the block(s). | 739 | * Invalidate the block(s). |
@@ -776,7 +748,7 @@ xfs_inactive_symlink_rmt( | |||
776 | * Unmap the dead block(s) to the free_list. | 748 | * Unmap the dead block(s) to the free_list. |
777 | */ | 749 | */ |
778 | if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, | 750 | if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, |
779 | &first_block, &free_list, NULL, &done))) | 751 | &first_block, &free_list, &done))) |
780 | goto error1; | 752 | goto error1; |
781 | ASSERT(done); | 753 | ASSERT(done); |
782 | /* | 754 | /* |
@@ -795,8 +767,7 @@ xfs_inactive_symlink_rmt( | |||
795 | * Mark it dirty so it will be logged and moved forward in the log as | 767 | * Mark it dirty so it will be logged and moved forward in the log as |
796 | * part of every commit. | 768 | * part of every commit. |
797 | */ | 769 | */ |
798 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | 770 | xfs_trans_ijoin(tp, ip); |
799 | xfs_trans_ihold(tp, ip); | ||
800 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 771 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
801 | /* | 772 | /* |
802 | * Get a new, empty transaction to return to our caller. | 773 | * Get a new, empty transaction to return to our caller. |
@@ -929,8 +900,7 @@ xfs_inactive_attrs( | |||
929 | goto error_cancel; | 900 | goto error_cancel; |
930 | 901 | ||
931 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 902 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
932 | xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | 903 | xfs_trans_ijoin(tp, ip); |
933 | xfs_trans_ihold(tp, ip); | ||
934 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); | 904 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); |
935 | 905 | ||
936 | ASSERT(ip->i_d.di_anextents == 0); | 906 | ASSERT(ip->i_d.di_anextents == 0); |
@@ -1035,8 +1005,6 @@ xfs_inactive( | |||
1035 | int error; | 1005 | int error; |
1036 | int truncate; | 1006 | int truncate; |
1037 | 1007 | ||
1038 | xfs_itrace_entry(ip); | ||
1039 | |||
1040 | /* | 1008 | /* |
1041 | * If the inode is already free, then there can be nothing | 1009 | * If the inode is already free, then there can be nothing |
1042 | * to clean up here. | 1010 | * to clean up here. |
@@ -1060,9 +1028,6 @@ xfs_inactive( | |||
1060 | 1028 | ||
1061 | mp = ip->i_mount; | 1029 | mp = ip->i_mount; |
1062 | 1030 | ||
1063 | if (ip->i_d.di_nlink == 0 && DM_EVENT_ENABLED(ip, DM_EVENT_DESTROY)) | ||
1064 | XFS_SEND_DESTROY(mp, ip, DM_RIGHT_NULL); | ||
1065 | |||
1066 | error = 0; | 1031 | error = 0; |
1067 | 1032 | ||
1068 | /* If this is a read-only mount, don't do this (would generate I/O) */ | 1033 | /* If this is a read-only mount, don't do this (would generate I/O) */ |
@@ -1120,8 +1085,7 @@ xfs_inactive( | |||
1120 | } | 1085 | } |
1121 | 1086 | ||
1122 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 1087 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
1123 | xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | 1088 | xfs_trans_ijoin(tp, ip); |
1124 | xfs_trans_ihold(tp, ip); | ||
1125 | 1089 | ||
1126 | /* | 1090 | /* |
1127 | * normally, we have to run xfs_itruncate_finish sync. | 1091 | * normally, we have to run xfs_itruncate_finish sync. |
@@ -1154,8 +1118,7 @@ xfs_inactive( | |||
1154 | return VN_INACTIVE_CACHE; | 1118 | return VN_INACTIVE_CACHE; |
1155 | } | 1119 | } |
1156 | 1120 | ||
1157 | xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | 1121 | xfs_trans_ijoin(tp, ip); |
1158 | xfs_trans_ihold(tp, ip); | ||
1159 | } else { | 1122 | } else { |
1160 | error = xfs_trans_reserve(tp, 0, | 1123 | error = xfs_trans_reserve(tp, 0, |
1161 | XFS_IFREE_LOG_RES(mp), | 1124 | XFS_IFREE_LOG_RES(mp), |
@@ -1168,8 +1131,7 @@ xfs_inactive( | |||
1168 | } | 1131 | } |
1169 | 1132 | ||
1170 | xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | 1133 | xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
1171 | xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL); | 1134 | xfs_trans_ijoin(tp, ip); |
1172 | xfs_trans_ihold(tp, ip); | ||
1173 | } | 1135 | } |
1174 | 1136 | ||
1175 | /* | 1137 | /* |
@@ -1257,7 +1219,7 @@ xfs_lookup( | |||
1257 | int error; | 1219 | int error; |
1258 | uint lock_mode; | 1220 | uint lock_mode; |
1259 | 1221 | ||
1260 | xfs_itrace_entry(dp); | 1222 | trace_xfs_lookup(dp, name); |
1261 | 1223 | ||
1262 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) | 1224 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) |
1263 | return XFS_ERROR(EIO); | 1225 | return XFS_ERROR(EIO); |
@@ -1309,21 +1271,11 @@ xfs_create( | |||
1309 | uint log_res; | 1271 | uint log_res; |
1310 | uint log_count; | 1272 | uint log_count; |
1311 | 1273 | ||
1312 | xfs_itrace_entry(dp); | 1274 | trace_xfs_create(dp, name); |
1313 | 1275 | ||
1314 | if (XFS_FORCED_SHUTDOWN(mp)) | 1276 | if (XFS_FORCED_SHUTDOWN(mp)) |
1315 | return XFS_ERROR(EIO); | 1277 | return XFS_ERROR(EIO); |
1316 | 1278 | ||
1317 | if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) { | ||
1318 | error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE, | ||
1319 | dp, DM_RIGHT_NULL, NULL, | ||
1320 | DM_RIGHT_NULL, name->name, NULL, | ||
1321 | mode, 0, 0); | ||
1322 | |||
1323 | if (error) | ||
1324 | return error; | ||
1325 | } | ||
1326 | |||
1327 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) | 1279 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) |
1328 | prid = dp->i_d.di_projid; | 1280 | prid = dp->i_d.di_projid; |
1329 | else | 1281 | else |
@@ -1427,8 +1379,7 @@ xfs_create( | |||
1427 | * the transaction cancel unlocking dp so don't do it explicitly in the | 1379 | * the transaction cancel unlocking dp so don't do it explicitly in the |
1428 | * error path. | 1380 | * error path. |
1429 | */ | 1381 | */ |
1430 | IHOLD(dp); | 1382 | xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL); |
1431 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); | ||
1432 | unlock_dp_on_error = B_FALSE; | 1383 | unlock_dp_on_error = B_FALSE; |
1433 | 1384 | ||
1434 | error = xfs_dir_createname(tp, dp, name, ip->i_ino, | 1385 | error = xfs_dir_createname(tp, dp, name, ip->i_ino, |
@@ -1487,16 +1438,7 @@ xfs_create( | |||
1487 | xfs_qm_dqrele(gdqp); | 1438 | xfs_qm_dqrele(gdqp); |
1488 | 1439 | ||
1489 | *ipp = ip; | 1440 | *ipp = ip; |
1490 | 1441 | return 0; | |
1491 | /* Fallthrough to std_return with error = 0 */ | ||
1492 | std_return: | ||
1493 | if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) { | ||
1494 | XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE, dp, DM_RIGHT_NULL, | ||
1495 | ip, DM_RIGHT_NULL, name->name, NULL, mode, | ||
1496 | error, 0); | ||
1497 | } | ||
1498 | |||
1499 | return error; | ||
1500 | 1442 | ||
1501 | out_bmap_cancel: | 1443 | out_bmap_cancel: |
1502 | xfs_bmap_cancel(&free_list); | 1444 | xfs_bmap_cancel(&free_list); |
@@ -1510,8 +1452,8 @@ xfs_create( | |||
1510 | 1452 | ||
1511 | if (unlock_dp_on_error) | 1453 | if (unlock_dp_on_error) |
1512 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 1454 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
1513 | 1455 | std_return: | |
1514 | goto std_return; | 1456 | return error; |
1515 | 1457 | ||
1516 | out_abort_rele: | 1458 | out_abort_rele: |
1517 | /* | 1459 | /* |
@@ -1726,20 +1668,11 @@ xfs_remove( | |||
1726 | uint resblks; | 1668 | uint resblks; |
1727 | uint log_count; | 1669 | uint log_count; |
1728 | 1670 | ||
1729 | xfs_itrace_entry(dp); | 1671 | trace_xfs_remove(dp, name); |
1730 | xfs_itrace_entry(ip); | ||
1731 | 1672 | ||
1732 | if (XFS_FORCED_SHUTDOWN(mp)) | 1673 | if (XFS_FORCED_SHUTDOWN(mp)) |
1733 | return XFS_ERROR(EIO); | 1674 | return XFS_ERROR(EIO); |
1734 | 1675 | ||
1735 | if (DM_EVENT_ENABLED(dp, DM_EVENT_REMOVE)) { | ||
1736 | error = XFS_SEND_NAMESP(mp, DM_EVENT_REMOVE, dp, DM_RIGHT_NULL, | ||
1737 | NULL, DM_RIGHT_NULL, name->name, NULL, | ||
1738 | ip->i_d.di_mode, 0, 0); | ||
1739 | if (error) | ||
1740 | return error; | ||
1741 | } | ||
1742 | |||
1743 | error = xfs_qm_dqattach(dp, 0); | 1676 | error = xfs_qm_dqattach(dp, 0); |
1744 | if (error) | 1677 | if (error) |
1745 | goto std_return; | 1678 | goto std_return; |
@@ -1782,15 +1715,8 @@ xfs_remove( | |||
1782 | 1715 | ||
1783 | xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL); | 1716 | xfs_lock_two_inodes(dp, ip, XFS_ILOCK_EXCL); |
1784 | 1717 | ||
1785 | /* | 1718 | xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL); |
1786 | * At this point, we've gotten both the directory and the entry | 1719 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); |
1787 | * inodes locked. | ||
1788 | */ | ||
1789 | IHOLD(ip); | ||
1790 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); | ||
1791 | |||
1792 | IHOLD(dp); | ||
1793 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
1794 | 1720 | ||
1795 | /* | 1721 | /* |
1796 | * If we're removing a directory perform some additional validation. | 1722 | * If we're removing a directory perform some additional validation. |
@@ -1877,21 +1803,15 @@ xfs_remove( | |||
1877 | if (!is_dir && link_zero && xfs_inode_is_filestream(ip)) | 1803 | if (!is_dir && link_zero && xfs_inode_is_filestream(ip)) |
1878 | xfs_filestream_deassociate(ip); | 1804 | xfs_filestream_deassociate(ip); |
1879 | 1805 | ||
1880 | std_return: | 1806 | return 0; |
1881 | if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTREMOVE)) { | ||
1882 | XFS_SEND_NAMESP(mp, DM_EVENT_POSTREMOVE, dp, DM_RIGHT_NULL, | ||
1883 | NULL, DM_RIGHT_NULL, name->name, NULL, | ||
1884 | ip->i_d.di_mode, error, 0); | ||
1885 | } | ||
1886 | |||
1887 | return error; | ||
1888 | 1807 | ||
1889 | out_bmap_cancel: | 1808 | out_bmap_cancel: |
1890 | xfs_bmap_cancel(&free_list); | 1809 | xfs_bmap_cancel(&free_list); |
1891 | cancel_flags |= XFS_TRANS_ABORT; | 1810 | cancel_flags |= XFS_TRANS_ABORT; |
1892 | out_trans_cancel: | 1811 | out_trans_cancel: |
1893 | xfs_trans_cancel(tp, cancel_flags); | 1812 | xfs_trans_cancel(tp, cancel_flags); |
1894 | goto std_return; | 1813 | std_return: |
1814 | return error; | ||
1895 | } | 1815 | } |
1896 | 1816 | ||
1897 | int | 1817 | int |
@@ -1909,25 +1829,13 @@ xfs_link( | |||
1909 | int committed; | 1829 | int committed; |
1910 | int resblks; | 1830 | int resblks; |
1911 | 1831 | ||
1912 | xfs_itrace_entry(tdp); | 1832 | trace_xfs_link(tdp, target_name); |
1913 | xfs_itrace_entry(sip); | ||
1914 | 1833 | ||
1915 | ASSERT(!S_ISDIR(sip->i_d.di_mode)); | 1834 | ASSERT(!S_ISDIR(sip->i_d.di_mode)); |
1916 | 1835 | ||
1917 | if (XFS_FORCED_SHUTDOWN(mp)) | 1836 | if (XFS_FORCED_SHUTDOWN(mp)) |
1918 | return XFS_ERROR(EIO); | 1837 | return XFS_ERROR(EIO); |
1919 | 1838 | ||
1920 | if (DM_EVENT_ENABLED(tdp, DM_EVENT_LINK)) { | ||
1921 | error = XFS_SEND_NAMESP(mp, DM_EVENT_LINK, | ||
1922 | tdp, DM_RIGHT_NULL, | ||
1923 | sip, DM_RIGHT_NULL, | ||
1924 | target_name->name, NULL, 0, 0, 0); | ||
1925 | if (error) | ||
1926 | return error; | ||
1927 | } | ||
1928 | |||
1929 | /* Return through std_return after this point. */ | ||
1930 | |||
1931 | error = xfs_qm_dqattach(sip, 0); | 1839 | error = xfs_qm_dqattach(sip, 0); |
1932 | if (error) | 1840 | if (error) |
1933 | goto std_return; | 1841 | goto std_return; |
@@ -1953,15 +1861,8 @@ xfs_link( | |||
1953 | 1861 | ||
1954 | xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL); | 1862 | xfs_lock_two_inodes(sip, tdp, XFS_ILOCK_EXCL); |
1955 | 1863 | ||
1956 | /* | 1864 | xfs_trans_ijoin_ref(tp, sip, XFS_ILOCK_EXCL); |
1957 | * Increment vnode ref counts since xfs_trans_commit & | 1865 | xfs_trans_ijoin_ref(tp, tdp, XFS_ILOCK_EXCL); |
1958 | * xfs_trans_cancel will both unlock the inodes and | ||
1959 | * decrement the associated ref counts. | ||
1960 | */ | ||
1961 | IHOLD(sip); | ||
1962 | IHOLD(tdp); | ||
1963 | xfs_trans_ijoin(tp, sip, XFS_ILOCK_EXCL); | ||
1964 | xfs_trans_ijoin(tp, tdp, XFS_ILOCK_EXCL); | ||
1965 | 1866 | ||
1966 | /* | 1867 | /* |
1967 | * If the source has too many links, we can't make any more to it. | 1868 | * If the source has too many links, we can't make any more to it. |
@@ -2014,27 +1915,14 @@ xfs_link( | |||
2014 | goto abort_return; | 1915 | goto abort_return; |
2015 | } | 1916 | } |
2016 | 1917 | ||
2017 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | 1918 | return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); |
2018 | if (error) | ||
2019 | goto std_return; | ||
2020 | |||
2021 | /* Fall through to std_return with error = 0. */ | ||
2022 | std_return: | ||
2023 | if (DM_EVENT_ENABLED(sip, DM_EVENT_POSTLINK)) { | ||
2024 | (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTLINK, | ||
2025 | tdp, DM_RIGHT_NULL, | ||
2026 | sip, DM_RIGHT_NULL, | ||
2027 | target_name->name, NULL, 0, error, 0); | ||
2028 | } | ||
2029 | return error; | ||
2030 | 1919 | ||
2031 | abort_return: | 1920 | abort_return: |
2032 | cancel_flags |= XFS_TRANS_ABORT; | 1921 | cancel_flags |= XFS_TRANS_ABORT; |
2033 | /* FALLTHROUGH */ | ||
2034 | |||
2035 | error_return: | 1922 | error_return: |
2036 | xfs_trans_cancel(tp, cancel_flags); | 1923 | xfs_trans_cancel(tp, cancel_flags); |
2037 | goto std_return; | 1924 | std_return: |
1925 | return error; | ||
2038 | } | 1926 | } |
2039 | 1927 | ||
2040 | int | 1928 | int |
@@ -2074,7 +1962,7 @@ xfs_symlink( | |||
2074 | ip = NULL; | 1962 | ip = NULL; |
2075 | tp = NULL; | 1963 | tp = NULL; |
2076 | 1964 | ||
2077 | xfs_itrace_entry(dp); | 1965 | trace_xfs_symlink(dp, link_name); |
2078 | 1966 | ||
2079 | if (XFS_FORCED_SHUTDOWN(mp)) | 1967 | if (XFS_FORCED_SHUTDOWN(mp)) |
2080 | return XFS_ERROR(EIO); | 1968 | return XFS_ERROR(EIO); |
@@ -2086,17 +1974,6 @@ xfs_symlink( | |||
2086 | if (pathlen >= MAXPATHLEN) /* total string too long */ | 1974 | if (pathlen >= MAXPATHLEN) /* total string too long */ |
2087 | return XFS_ERROR(ENAMETOOLONG); | 1975 | return XFS_ERROR(ENAMETOOLONG); |
2088 | 1976 | ||
2089 | if (DM_EVENT_ENABLED(dp, DM_EVENT_SYMLINK)) { | ||
2090 | error = XFS_SEND_NAMESP(mp, DM_EVENT_SYMLINK, dp, | ||
2091 | DM_RIGHT_NULL, NULL, DM_RIGHT_NULL, | ||
2092 | link_name->name, | ||
2093 | (unsigned char *)target_path, 0, 0, 0); | ||
2094 | if (error) | ||
2095 | return error; | ||
2096 | } | ||
2097 | |||
2098 | /* Return through std_return after this point. */ | ||
2099 | |||
2100 | udqp = gdqp = NULL; | 1977 | udqp = gdqp = NULL; |
2101 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) | 1978 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) |
2102 | prid = dp->i_d.di_projid; | 1979 | prid = dp->i_d.di_projid; |
@@ -2180,8 +2057,7 @@ xfs_symlink( | |||
2180 | * transaction cancel unlocking dp so don't do it explicitly in the | 2057 | * transaction cancel unlocking dp so don't do it explicitly in the |
2181 | * error path. | 2058 | * error path. |
2182 | */ | 2059 | */ |
2183 | IHOLD(dp); | 2060 | xfs_trans_ijoin_ref(tp, dp, XFS_ILOCK_EXCL); |
2184 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); | ||
2185 | unlock_dp_on_error = B_FALSE; | 2061 | unlock_dp_on_error = B_FALSE; |
2186 | 2062 | ||
2187 | /* | 2063 | /* |
@@ -2215,7 +2091,7 @@ xfs_symlink( | |||
2215 | error = xfs_bmapi(tp, ip, first_fsb, fs_blocks, | 2091 | error = xfs_bmapi(tp, ip, first_fsb, fs_blocks, |
2216 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, | 2092 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, |
2217 | &first_block, resblks, mval, &nmaps, | 2093 | &first_block, resblks, mval, &nmaps, |
2218 | &free_list, NULL); | 2094 | &free_list); |
2219 | if (error) { | 2095 | if (error) { |
2220 | goto error1; | 2096 | goto error1; |
2221 | } | 2097 | } |
@@ -2278,21 +2154,8 @@ xfs_symlink( | |||
2278 | xfs_qm_dqrele(udqp); | 2154 | xfs_qm_dqrele(udqp); |
2279 | xfs_qm_dqrele(gdqp); | 2155 | xfs_qm_dqrele(gdqp); |
2280 | 2156 | ||
2281 | /* Fall through to std_return with error = 0 or errno from | 2157 | *ipp = ip; |
2282 | * xfs_trans_commit */ | 2158 | return 0; |
2283 | std_return: | ||
2284 | if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTSYMLINK)) { | ||
2285 | (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTSYMLINK, | ||
2286 | dp, DM_RIGHT_NULL, | ||
2287 | error ? NULL : ip, | ||
2288 | DM_RIGHT_NULL, link_name->name, | ||
2289 | (unsigned char *)target_path, | ||
2290 | 0, error, 0); | ||
2291 | } | ||
2292 | |||
2293 | if (!error) | ||
2294 | *ipp = ip; | ||
2295 | return error; | ||
2296 | 2159 | ||
2297 | error2: | 2160 | error2: |
2298 | IRELE(ip); | 2161 | IRELE(ip); |
@@ -2306,8 +2169,8 @@ std_return: | |||
2306 | 2169 | ||
2307 | if (unlock_dp_on_error) | 2170 | if (unlock_dp_on_error) |
2308 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | 2171 | xfs_iunlock(dp, XFS_ILOCK_EXCL); |
2309 | 2172 | std_return: | |
2310 | goto std_return; | 2173 | return error; |
2311 | } | 2174 | } |
2312 | 2175 | ||
2313 | int | 2176 | int |
@@ -2333,13 +2196,12 @@ xfs_set_dmattrs( | |||
2333 | return error; | 2196 | return error; |
2334 | } | 2197 | } |
2335 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 2198 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
2336 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 2199 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); |
2337 | 2200 | ||
2338 | ip->i_d.di_dmevmask = evmask; | 2201 | ip->i_d.di_dmevmask = evmask; |
2339 | ip->i_d.di_dmstate = state; | 2202 | ip->i_d.di_dmstate = state; |
2340 | 2203 | ||
2341 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 2204 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
2342 | IHOLD(ip); | ||
2343 | error = xfs_trans_commit(tp, 0); | 2205 | error = xfs_trans_commit(tp, 0); |
2344 | 2206 | ||
2345 | return error; | 2207 | return error; |
@@ -2390,7 +2252,7 @@ xfs_alloc_file_space( | |||
2390 | int committed; | 2252 | int committed; |
2391 | int error; | 2253 | int error; |
2392 | 2254 | ||
2393 | xfs_itrace_entry(ip); | 2255 | trace_xfs_alloc_file_space(ip); |
2394 | 2256 | ||
2395 | if (XFS_FORCED_SHUTDOWN(mp)) | 2257 | if (XFS_FORCED_SHUTDOWN(mp)) |
2396 | return XFS_ERROR(EIO); | 2258 | return XFS_ERROR(EIO); |
@@ -2412,25 +2274,9 @@ xfs_alloc_file_space( | |||
2412 | startoffset_fsb = XFS_B_TO_FSBT(mp, offset); | 2274 | startoffset_fsb = XFS_B_TO_FSBT(mp, offset); |
2413 | allocatesize_fsb = XFS_B_TO_FSB(mp, count); | 2275 | allocatesize_fsb = XFS_B_TO_FSB(mp, count); |
2414 | 2276 | ||
2415 | /* Generate a DMAPI event if needed. */ | ||
2416 | if (alloc_type != 0 && offset < ip->i_size && | ||
2417 | (attr_flags & XFS_ATTR_DMI) == 0 && | ||
2418 | DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) { | ||
2419 | xfs_off_t end_dmi_offset; | ||
2420 | |||
2421 | end_dmi_offset = offset+len; | ||
2422 | if (end_dmi_offset > ip->i_size) | ||
2423 | end_dmi_offset = ip->i_size; | ||
2424 | error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip, offset, | ||
2425 | end_dmi_offset - offset, 0, NULL); | ||
2426 | if (error) | ||
2427 | return error; | ||
2428 | } | ||
2429 | |||
2430 | /* | 2277 | /* |
2431 | * Allocate file space until done or until there is an error | 2278 | * Allocate file space until done or until there is an error |
2432 | */ | 2279 | */ |
2433 | retry: | ||
2434 | while (allocatesize_fsb && !error) { | 2280 | while (allocatesize_fsb && !error) { |
2435 | xfs_fileoff_t s, e; | 2281 | xfs_fileoff_t s, e; |
2436 | 2282 | ||
@@ -2488,8 +2334,7 @@ retry: | |||
2488 | if (error) | 2334 | if (error) |
2489 | goto error1; | 2335 | goto error1; |
2490 | 2336 | ||
2491 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 2337 | xfs_trans_ijoin(tp, ip); |
2492 | xfs_trans_ihold(tp, ip); | ||
2493 | 2338 | ||
2494 | /* | 2339 | /* |
2495 | * Issue the xfs_bmapi() call to allocate the blocks | 2340 | * Issue the xfs_bmapi() call to allocate the blocks |
@@ -2498,7 +2343,7 @@ retry: | |||
2498 | error = xfs_bmapi(tp, ip, startoffset_fsb, | 2343 | error = xfs_bmapi(tp, ip, startoffset_fsb, |
2499 | allocatesize_fsb, bmapi_flag, | 2344 | allocatesize_fsb, bmapi_flag, |
2500 | &firstfsb, 0, imapp, &nimaps, | 2345 | &firstfsb, 0, imapp, &nimaps, |
2501 | &free_list, NULL); | 2346 | &free_list); |
2502 | if (error) { | 2347 | if (error) { |
2503 | goto error0; | 2348 | goto error0; |
2504 | } | 2349 | } |
@@ -2527,17 +2372,6 @@ retry: | |||
2527 | startoffset_fsb += allocated_fsb; | 2372 | startoffset_fsb += allocated_fsb; |
2528 | allocatesize_fsb -= allocated_fsb; | 2373 | allocatesize_fsb -= allocated_fsb; |
2529 | } | 2374 | } |
2530 | dmapi_enospc_check: | ||
2531 | if (error == ENOSPC && (attr_flags & XFS_ATTR_DMI) == 0 && | ||
2532 | DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE)) { | ||
2533 | error = XFS_SEND_NAMESP(mp, DM_EVENT_NOSPACE, | ||
2534 | ip, DM_RIGHT_NULL, | ||
2535 | ip, DM_RIGHT_NULL, | ||
2536 | NULL, NULL, 0, 0, 0); /* Delay flag intentionally unused */ | ||
2537 | if (error == 0) | ||
2538 | goto retry; /* Maybe DMAPI app. has made space */ | ||
2539 | /* else fall through with error from XFS_SEND_DATA */ | ||
2540 | } | ||
2541 | 2375 | ||
2542 | return error; | 2376 | return error; |
2543 | 2377 | ||
@@ -2548,7 +2382,7 @@ error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */ | |||
2548 | error1: /* Just cancel transaction */ | 2382 | error1: /* Just cancel transaction */ |
2549 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | 2383 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); |
2550 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 2384 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
2551 | goto dmapi_enospc_check; | 2385 | return error; |
2552 | } | 2386 | } |
2553 | 2387 | ||
2554 | /* | 2388 | /* |
@@ -2598,7 +2432,7 @@ xfs_zero_remaining_bytes( | |||
2598 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 2432 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
2599 | nimap = 1; | 2433 | nimap = 1; |
2600 | error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0, | 2434 | error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0, |
2601 | NULL, 0, &imap, &nimap, NULL, NULL); | 2435 | NULL, 0, &imap, &nimap, NULL); |
2602 | if (error || nimap < 1) | 2436 | if (error || nimap < 1) |
2603 | break; | 2437 | break; |
2604 | ASSERT(imap.br_blockcount >= 1); | 2438 | ASSERT(imap.br_blockcount >= 1); |
@@ -2661,7 +2495,6 @@ xfs_free_file_space( | |||
2661 | { | 2495 | { |
2662 | int committed; | 2496 | int committed; |
2663 | int done; | 2497 | int done; |
2664 | xfs_off_t end_dmi_offset; | ||
2665 | xfs_fileoff_t endoffset_fsb; | 2498 | xfs_fileoff_t endoffset_fsb; |
2666 | int error; | 2499 | int error; |
2667 | xfs_fsblock_t firstfsb; | 2500 | xfs_fsblock_t firstfsb; |
@@ -2680,7 +2513,7 @@ xfs_free_file_space( | |||
2680 | 2513 | ||
2681 | mp = ip->i_mount; | 2514 | mp = ip->i_mount; |
2682 | 2515 | ||
2683 | xfs_itrace_entry(ip); | 2516 | trace_xfs_free_file_space(ip); |
2684 | 2517 | ||
2685 | error = xfs_qm_dqattach(ip, 0); | 2518 | error = xfs_qm_dqattach(ip, 0); |
2686 | if (error) | 2519 | if (error) |
@@ -2691,19 +2524,7 @@ xfs_free_file_space( | |||
2691 | return error; | 2524 | return error; |
2692 | rt = XFS_IS_REALTIME_INODE(ip); | 2525 | rt = XFS_IS_REALTIME_INODE(ip); |
2693 | startoffset_fsb = XFS_B_TO_FSB(mp, offset); | 2526 | startoffset_fsb = XFS_B_TO_FSB(mp, offset); |
2694 | end_dmi_offset = offset + len; | 2527 | endoffset_fsb = XFS_B_TO_FSBT(mp, offset + len); |
2695 | endoffset_fsb = XFS_B_TO_FSBT(mp, end_dmi_offset); | ||
2696 | |||
2697 | if (offset < ip->i_size && (attr_flags & XFS_ATTR_DMI) == 0 && | ||
2698 | DM_EVENT_ENABLED(ip, DM_EVENT_WRITE)) { | ||
2699 | if (end_dmi_offset > ip->i_size) | ||
2700 | end_dmi_offset = ip->i_size; | ||
2701 | error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip, | ||
2702 | offset, end_dmi_offset - offset, | ||
2703 | AT_DELAY_FLAG(attr_flags), NULL); | ||
2704 | if (error) | ||
2705 | return error; | ||
2706 | } | ||
2707 | 2528 | ||
2708 | if (attr_flags & XFS_ATTR_NOLOCK) | 2529 | if (attr_flags & XFS_ATTR_NOLOCK) |
2709 | need_iolock = 0; | 2530 | need_iolock = 0; |
@@ -2731,7 +2552,7 @@ xfs_free_file_space( | |||
2731 | if (rt && !xfs_sb_version_hasextflgbit(&mp->m_sb)) { | 2552 | if (rt && !xfs_sb_version_hasextflgbit(&mp->m_sb)) { |
2732 | nimap = 1; | 2553 | nimap = 1; |
2733 | error = xfs_bmapi(NULL, ip, startoffset_fsb, | 2554 | error = xfs_bmapi(NULL, ip, startoffset_fsb, |
2734 | 1, 0, NULL, 0, &imap, &nimap, NULL, NULL); | 2555 | 1, 0, NULL, 0, &imap, &nimap, NULL); |
2735 | if (error) | 2556 | if (error) |
2736 | goto out_unlock_iolock; | 2557 | goto out_unlock_iolock; |
2737 | ASSERT(nimap == 0 || nimap == 1); | 2558 | ASSERT(nimap == 0 || nimap == 1); |
@@ -2746,7 +2567,7 @@ xfs_free_file_space( | |||
2746 | } | 2567 | } |
2747 | nimap = 1; | 2568 | nimap = 1; |
2748 | error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, | 2569 | error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, |
2749 | 1, 0, NULL, 0, &imap, &nimap, NULL, NULL); | 2570 | 1, 0, NULL, 0, &imap, &nimap, NULL); |
2750 | if (error) | 2571 | if (error) |
2751 | goto out_unlock_iolock; | 2572 | goto out_unlock_iolock; |
2752 | ASSERT(nimap == 0 || nimap == 1); | 2573 | ASSERT(nimap == 0 || nimap == 1); |
@@ -2814,8 +2635,7 @@ xfs_free_file_space( | |||
2814 | if (error) | 2635 | if (error) |
2815 | goto error1; | 2636 | goto error1; |
2816 | 2637 | ||
2817 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 2638 | xfs_trans_ijoin(tp, ip); |
2818 | xfs_trans_ihold(tp, ip); | ||
2819 | 2639 | ||
2820 | /* | 2640 | /* |
2821 | * issue the bunmapi() call to free the blocks | 2641 | * issue the bunmapi() call to free the blocks |
@@ -2823,7 +2643,7 @@ xfs_free_file_space( | |||
2823 | xfs_bmap_init(&free_list, &firstfsb); | 2643 | xfs_bmap_init(&free_list, &firstfsb); |
2824 | error = xfs_bunmapi(tp, ip, startoffset_fsb, | 2644 | error = xfs_bunmapi(tp, ip, startoffset_fsb, |
2825 | endoffset_fsb - startoffset_fsb, | 2645 | endoffset_fsb - startoffset_fsb, |
2826 | 0, 2, &firstfsb, &free_list, NULL, &done); | 2646 | 0, 2, &firstfsb, &free_list, &done); |
2827 | if (error) { | 2647 | if (error) { |
2828 | goto error0; | 2648 | goto error0; |
2829 | } | 2649 | } |
@@ -2883,8 +2703,6 @@ xfs_change_file_space( | |||
2883 | xfs_trans_t *tp; | 2703 | xfs_trans_t *tp; |
2884 | struct iattr iattr; | 2704 | struct iattr iattr; |
2885 | 2705 | ||
2886 | xfs_itrace_entry(ip); | ||
2887 | |||
2888 | if (!S_ISREG(ip->i_d.di_mode)) | 2706 | if (!S_ISREG(ip->i_d.di_mode)) |
2889 | return XFS_ERROR(EINVAL); | 2707 | return XFS_ERROR(EINVAL); |
2890 | 2708 | ||
@@ -2985,8 +2803,7 @@ xfs_change_file_space( | |||
2985 | 2803 | ||
2986 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 2804 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
2987 | 2805 | ||
2988 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | 2806 | xfs_trans_ijoin(tp, ip); |
2989 | xfs_trans_ihold(tp, ip); | ||
2990 | 2807 | ||
2991 | if ((attr_flags & XFS_ATTR_DMI) == 0) { | 2808 | if ((attr_flags & XFS_ATTR_DMI) == 0) { |
2992 | ip->i_d.di_mode &= ~S_ISUID; | 2809 | ip->i_d.di_mode &= ~S_ISUID; |