@@ -28,37 +28,50 @@ const struct file_operations sysv_dir_operations = {
28
28
.fsync = generic_file_fsync ,
29
29
};
30
30
31
- static inline void dir_put_page (struct page * page )
31
+ inline void dir_put_page (struct page * page , void * page_addr )
32
32
{
33
- kunmap ( page );
33
+ kunmap_local (( void * )(( unsigned long ) page_addr & PAGE_MASK ) );
34
34
put_page (page );
35
35
}
36
36
37
- static int dir_commit_chunk (struct page * page , loff_t pos , unsigned len )
37
+ static void dir_commit_chunk (struct page * page , loff_t pos , unsigned len )
38
38
{
39
39
struct address_space * mapping = page -> mapping ;
40
40
struct inode * dir = mapping -> host ;
41
- int err = 0 ;
42
41
43
42
block_write_end (NULL , mapping , pos , len , len , page , NULL );
44
43
if (pos + len > dir -> i_size ) {
45
44
i_size_write (dir , pos + len );
46
45
mark_inode_dirty (dir );
47
46
}
48
- if (IS_DIRSYNC (dir ))
49
- err = write_one_page (page );
50
- else
51
- unlock_page (page );
47
+ unlock_page (page );
48
+ }
49
+
50
+ static int sysv_handle_dirsync (struct inode * dir )
51
+ {
52
+ int err ;
53
+
54
+ err = filemap_write_and_wait (dir -> i_mapping );
55
+ if (!err )
56
+ err = sync_inode_metadata (dir , 1 );
52
57
return err ;
53
58
}
54
59
55
- static struct page * dir_get_page (struct inode * dir , unsigned long n )
60
+ /*
61
+ * Calls to dir_get_page()/dir_put_page() must be nested according to the
62
+ * rules documented in mm/highmem.rst.
63
+ *
64
+ * NOTE: sysv_find_entry() and sysv_dotdot() act as calls to dir_get_page()
65
+ * and must be treated accordingly for nesting purposes.
66
+ */
67
+ static void * dir_get_page (struct inode * dir , unsigned long n , struct page * * p )
56
68
{
57
69
struct address_space * mapping = dir -> i_mapping ;
58
70
struct page * page = read_mapping_page (mapping , n , NULL );
59
- if (!IS_ERR (page ))
60
- kmap (page );
61
- return page ;
71
+ if (IS_ERR (page ))
72
+ return ERR_CAST (page );
73
+ * p = page ;
74
+ return kmap_local_page (page );
62
75
}
63
76
64
77
static int sysv_readdir (struct file * file , struct dir_context * ctx )
@@ -80,11 +93,11 @@ static int sysv_readdir(struct file *file, struct dir_context *ctx)
80
93
for ( ; n < npages ; n ++ , offset = 0 ) {
81
94
char * kaddr , * limit ;
82
95
struct sysv_dir_entry * de ;
83
- struct page * page = dir_get_page ( inode , n ) ;
96
+ struct page * page ;
84
97
85
- if (IS_ERR (page ))
98
+ kaddr = dir_get_page (inode , n , & page );
99
+ if (IS_ERR (kaddr ))
86
100
continue ;
87
- kaddr = (char * )page_address (page );
88
101
de = (struct sysv_dir_entry * )(kaddr + offset );
89
102
limit = kaddr + PAGE_SIZE - SYSV_DIRSIZE ;
90
103
for ( ;(char * )de <= limit ; de ++ , ctx -> pos += sizeof (* de )) {
@@ -96,11 +109,11 @@ static int sysv_readdir(struct file *file, struct dir_context *ctx)
96
109
if (!dir_emit (ctx , name , strnlen (name ,SYSV_NAMELEN ),
97
110
fs16_to_cpu (SYSV_SB (sb ), de -> inode ),
98
111
DT_UNKNOWN )) {
99
- dir_put_page (page );
112
+ dir_put_page (page , kaddr );
100
113
return 0 ;
101
114
}
102
115
}
103
- dir_put_page (page );
116
+ dir_put_page (page , kaddr );
104
117
}
105
118
return 0 ;
106
119
}
@@ -123,6 +136,11 @@ static inline int namecompare(int len, int maxlen,
123
136
* returns the cache buffer in which the entry was found, and the entry
124
137
* itself (as a parameter - res_dir). It does NOT read the inode of the
125
138
* entry - you'll have to do that yourself if you want to.
139
+ *
140
+ * On Success dir_put_page() should be called on *res_page.
141
+ *
142
+ * sysv_find_entry() acts as a call to dir_get_page() and must be treated
143
+ * accordingly for nesting purposes.
126
144
*/
127
145
struct sysv_dir_entry * sysv_find_entry (struct dentry * dentry , struct page * * res_page )
128
146
{
@@ -142,11 +160,10 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_
142
160
n = start ;
143
161
144
162
do {
145
- char * kaddr ;
146
- page = dir_get_page (dir , n );
147
- if (!IS_ERR (page )) {
148
- kaddr = (char * )page_address (page );
149
- de = (struct sysv_dir_entry * ) kaddr ;
163
+ char * kaddr = dir_get_page (dir , n , & page );
164
+
165
+ if (!IS_ERR (kaddr )) {
166
+ de = (struct sysv_dir_entry * )kaddr ;
150
167
kaddr += PAGE_SIZE - SYSV_DIRSIZE ;
151
168
for ( ; (char * ) de <= kaddr ; de ++ ) {
152
169
if (!de -> inode )
@@ -155,7 +172,7 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_
155
172
name , de -> name ))
156
173
goto found ;
157
174
}
158
- dir_put_page (page );
175
+ dir_put_page (page , kaddr );
159
176
}
160
177
161
178
if (++ n >= npages )
@@ -185,11 +202,9 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
185
202
186
203
/* We take care of directory expansion in the same loop */
187
204
for (n = 0 ; n <= npages ; n ++ ) {
188
- page = dir_get_page (dir , n );
189
- err = PTR_ERR (page );
190
- if (IS_ERR (page ))
191
- goto out ;
192
- kaddr = (char * )page_address (page );
205
+ kaddr = dir_get_page (dir , n , & page );
206
+ if (IS_ERR (kaddr ))
207
+ return PTR_ERR (kaddr );
193
208
de = (struct sysv_dir_entry * )kaddr ;
194
209
kaddr += PAGE_SIZE - SYSV_DIRSIZE ;
195
210
while ((char * )de <= kaddr ) {
@@ -200,27 +215,26 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
200
215
goto out_page ;
201
216
de ++ ;
202
217
}
203
- dir_put_page (page );
218
+ dir_put_page (page , kaddr );
204
219
}
205
220
BUG ();
206
221
return - EINVAL ;
207
222
208
223
got_it :
209
- pos = page_offset (page ) +
210
- (char * )de - (char * )page_address (page );
224
+ pos = page_offset (page ) + offset_in_page (de );
211
225
lock_page (page );
212
226
err = sysv_prepare_chunk (page , pos , SYSV_DIRSIZE );
213
227
if (err )
214
228
goto out_unlock ;
215
229
memcpy (de -> name , name , namelen );
216
230
memset (de -> name + namelen , 0 , SYSV_DIRSIZE - namelen - 2 );
217
231
de -> inode = cpu_to_fs16 (SYSV_SB (inode -> i_sb ), inode -> i_ino );
218
- err = dir_commit_chunk (page , pos , SYSV_DIRSIZE );
232
+ dir_commit_chunk (page , pos , SYSV_DIRSIZE );
219
233
dir -> i_mtime = dir -> i_ctime = current_time (dir );
220
234
mark_inode_dirty (dir );
235
+ err = sysv_handle_dirsync (dir );
221
236
out_page :
222
- dir_put_page (page );
223
- out :
237
+ dir_put_page (page , kaddr );
224
238
return err ;
225
239
out_unlock :
226
240
unlock_page (page );
@@ -230,19 +244,20 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
230
244
int sysv_delete_entry (struct sysv_dir_entry * de , struct page * page )
231
245
{
232
246
struct inode * inode = page -> mapping -> host ;
233
- char * kaddr = (char * )page_address (page );
234
- loff_t pos = page_offset (page ) + (char * )de - kaddr ;
247
+ loff_t pos = page_offset (page ) + offset_in_page (de );
235
248
int err ;
236
249
237
250
lock_page (page );
238
251
err = sysv_prepare_chunk (page , pos , SYSV_DIRSIZE );
239
- BUG_ON (err );
252
+ if (err ) {
253
+ unlock_page (page );
254
+ return err ;
255
+ }
240
256
de -> inode = 0 ;
241
- err = dir_commit_chunk (page , pos , SYSV_DIRSIZE );
242
- dir_put_page (page );
257
+ dir_commit_chunk (page , pos , SYSV_DIRSIZE );
243
258
inode -> i_ctime = inode -> i_mtime = current_time (inode );
244
259
mark_inode_dirty (inode );
245
- return err ;
260
+ return sysv_handle_dirsync ( inode ) ;
246
261
}
247
262
248
263
int sysv_make_empty (struct inode * inode , struct inode * dir )
@@ -259,9 +274,7 @@ int sysv_make_empty(struct inode *inode, struct inode *dir)
259
274
unlock_page (page );
260
275
goto fail ;
261
276
}
262
- kmap (page );
263
-
264
- base = (char * )page_address (page );
277
+ base = kmap_local_page (page );
265
278
memset (base , 0 , PAGE_SIZE );
266
279
267
280
de = (struct sysv_dir_entry * ) base ;
@@ -271,8 +284,9 @@ int sysv_make_empty(struct inode *inode, struct inode *dir)
271
284
de -> inode = cpu_to_fs16 (SYSV_SB (inode -> i_sb ), dir -> i_ino );
272
285
strcpy (de -> name ,".." );
273
286
274
- kunmap (page );
275
- err = dir_commit_chunk (page , 0 , 2 * SYSV_DIRSIZE );
287
+ kunmap_local (base );
288
+ dir_commit_chunk (page , 0 , 2 * SYSV_DIRSIZE );
289
+ err = sysv_handle_dirsync (inode );
276
290
fail :
277
291
put_page (page );
278
292
return err ;
@@ -286,16 +300,15 @@ int sysv_empty_dir(struct inode * inode)
286
300
struct super_block * sb = inode -> i_sb ;
287
301
struct page * page = NULL ;
288
302
unsigned long i , npages = dir_pages (inode );
303
+ char * kaddr ;
289
304
290
305
for (i = 0 ; i < npages ; i ++ ) {
291
- char * kaddr ;
292
- struct sysv_dir_entry * de ;
293
- page = dir_get_page (inode , i );
306
+ struct sysv_dir_entry * de ;
294
307
295
- if (IS_ERR (page ))
308
+ kaddr = dir_get_page (inode , i , & page );
309
+ if (IS_ERR (kaddr ))
296
310
continue ;
297
311
298
- kaddr = (char * )page_address (page );
299
312
de = (struct sysv_dir_entry * )kaddr ;
300
313
kaddr += PAGE_SIZE - SYSV_DIRSIZE ;
301
314
@@ -314,44 +327,51 @@ int sysv_empty_dir(struct inode * inode)
314
327
if (de -> name [1 ] != '.' || de -> name [2 ])
315
328
goto not_empty ;
316
329
}
317
- dir_put_page (page );
330
+ dir_put_page (page , kaddr );
318
331
}
319
332
return 1 ;
320
333
321
334
not_empty :
322
- dir_put_page (page );
335
+ dir_put_page (page , kaddr );
323
336
return 0 ;
324
337
}
325
338
326
339
/* Releases the page */
327
- void sysv_set_link (struct sysv_dir_entry * de , struct page * page ,
340
+ int sysv_set_link (struct sysv_dir_entry * de , struct page * page ,
328
341
struct inode * inode )
329
342
{
330
343
struct inode * dir = page -> mapping -> host ;
331
- loff_t pos = page_offset (page ) +
332
- (char * )de - (char * )page_address (page );
344
+ loff_t pos = page_offset (page ) + offset_in_page (de );
333
345
int err ;
334
346
335
347
lock_page (page );
336
348
err = sysv_prepare_chunk (page , pos , SYSV_DIRSIZE );
337
- BUG_ON (err );
349
+ if (err ) {
350
+ unlock_page (page );
351
+ return err ;
352
+ }
338
353
de -> inode = cpu_to_fs16 (SYSV_SB (inode -> i_sb ), inode -> i_ino );
339
- err = dir_commit_chunk (page , pos , SYSV_DIRSIZE );
340
- dir_put_page (page );
354
+ dir_commit_chunk (page , pos , SYSV_DIRSIZE );
341
355
dir -> i_mtime = dir -> i_ctime = current_time (dir );
342
356
mark_inode_dirty (dir );
357
+ return sysv_handle_dirsync (inode );
343
358
}
344
359
345
- struct sysv_dir_entry * sysv_dotdot (struct inode * dir , struct page * * p )
360
+ /*
361
+ * Calls to dir_get_page()/dir_put_page() must be nested according to the
362
+ * rules documented in mm/highmem.rst.
363
+ *
364
+ * sysv_dotdot() acts as a call to dir_get_page() and must be treated
365
+ * accordingly for nesting purposes.
366
+ */
367
+ struct sysv_dir_entry * sysv_dotdot (struct inode * dir , struct page * * p )
346
368
{
347
- struct page * page = dir_get_page (dir , 0 );
348
- struct sysv_dir_entry * de = NULL ;
369
+ struct sysv_dir_entry * de = dir_get_page (dir , 0 , p );
349
370
350
- if (!IS_ERR (page )) {
351
- de = (struct sysv_dir_entry * ) page_address (page ) + 1 ;
352
- * p = page ;
353
- }
354
- return de ;
371
+ if (IS_ERR (de ))
372
+ return NULL ;
373
+ /* ".." is the second directory entry */
374
+ return de + 1 ;
355
375
}
356
376
357
377
ino_t sysv_inode_by_name (struct dentry * dentry )
@@ -362,7 +382,7 @@ ino_t sysv_inode_by_name(struct dentry *dentry)
362
382
363
383
if (de ) {
364
384
res = fs16_to_cpu (SYSV_SB (dentry -> d_sb ), de -> inode );
365
- dir_put_page (page );
385
+ dir_put_page (page , de );
366
386
}
367
387
return res ;
368
388
}
0 commit comments