@@ -28,37 +28,50 @@ const struct file_operations sysv_dir_operations = {
2828 .fsync = generic_file_fsync ,
2929};
3030
31- static inline void dir_put_page (struct page * page )
31+ inline void dir_put_page (struct page * page , void * page_addr )
3232{
33- kunmap ( page );
33+ kunmap_local (( void * )(( unsigned long ) page_addr & PAGE_MASK ) );
3434 put_page (page );
3535}
3636
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 )
3838{
3939 struct address_space * mapping = page -> mapping ;
4040 struct inode * dir = mapping -> host ;
41- int err = 0 ;
4241
4342 block_write_end (NULL , mapping , pos , len , len , page , NULL );
4443 if (pos + len > dir -> i_size ) {
4544 i_size_write (dir , pos + len );
4645 mark_inode_dirty (dir );
4746 }
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 );
5257 return err ;
5358}
5459
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 )
5668{
5769 struct address_space * mapping = dir -> i_mapping ;
5870 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 );
6275}
6376
6477static 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)
8093 for ( ; n < npages ; n ++ , offset = 0 ) {
8194 char * kaddr , * limit ;
8295 struct sysv_dir_entry * de ;
83- struct page * page = dir_get_page ( inode , n ) ;
96+ struct page * page ;
8497
85- if (IS_ERR (page ))
98+ kaddr = dir_get_page (inode , n , & page );
99+ if (IS_ERR (kaddr ))
86100 continue ;
87- kaddr = (char * )page_address (page );
88101 de = (struct sysv_dir_entry * )(kaddr + offset );
89102 limit = kaddr + PAGE_SIZE - SYSV_DIRSIZE ;
90103 for ( ;(char * )de <= limit ; de ++ , ctx -> pos += sizeof (* de )) {
@@ -96,11 +109,11 @@ static int sysv_readdir(struct file *file, struct dir_context *ctx)
96109 if (!dir_emit (ctx , name , strnlen (name ,SYSV_NAMELEN ),
97110 fs16_to_cpu (SYSV_SB (sb ), de -> inode ),
98111 DT_UNKNOWN )) {
99- dir_put_page (page );
112+ dir_put_page (page , kaddr );
100113 return 0 ;
101114 }
102115 }
103- dir_put_page (page );
116+ dir_put_page (page , kaddr );
104117 }
105118 return 0 ;
106119}
@@ -123,6 +136,11 @@ static inline int namecompare(int len, int maxlen,
123136 * returns the cache buffer in which the entry was found, and the entry
124137 * itself (as a parameter - res_dir). It does NOT read the inode of the
125138 * 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.
126144 */
127145struct sysv_dir_entry * sysv_find_entry (struct dentry * dentry , struct page * * res_page )
128146{
@@ -142,11 +160,10 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_
142160 n = start ;
143161
144162 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 ;
150167 kaddr += PAGE_SIZE - SYSV_DIRSIZE ;
151168 for ( ; (char * ) de <= kaddr ; de ++ ) {
152169 if (!de -> inode )
@@ -155,7 +172,7 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_
155172 name , de -> name ))
156173 goto found ;
157174 }
158- dir_put_page (page );
175+ dir_put_page (page , kaddr );
159176 }
160177
161178 if (++ n >= npages )
@@ -185,11 +202,9 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
185202
186203 /* We take care of directory expansion in the same loop */
187204 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 );
193208 de = (struct sysv_dir_entry * )kaddr ;
194209 kaddr += PAGE_SIZE - SYSV_DIRSIZE ;
195210 while ((char * )de <= kaddr ) {
@@ -200,27 +215,26 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
200215 goto out_page ;
201216 de ++ ;
202217 }
203- dir_put_page (page );
218+ dir_put_page (page , kaddr );
204219 }
205220 BUG ();
206221 return - EINVAL ;
207222
208223got_it :
209- pos = page_offset (page ) +
210- (char * )de - (char * )page_address (page );
224+ pos = page_offset (page ) + offset_in_page (de );
211225 lock_page (page );
212226 err = sysv_prepare_chunk (page , pos , SYSV_DIRSIZE );
213227 if (err )
214228 goto out_unlock ;
215229 memcpy (de -> name , name , namelen );
216230 memset (de -> name + namelen , 0 , SYSV_DIRSIZE - namelen - 2 );
217231 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 );
219233 dir -> i_mtime = dir -> i_ctime = current_time (dir );
220234 mark_inode_dirty (dir );
235+ err = sysv_handle_dirsync (dir );
221236out_page :
222- dir_put_page (page );
223- out :
237+ dir_put_page (page , kaddr );
224238 return err ;
225239out_unlock :
226240 unlock_page (page );
@@ -230,19 +244,20 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
230244int sysv_delete_entry (struct sysv_dir_entry * de , struct page * page )
231245{
232246 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 );
235248 int err ;
236249
237250 lock_page (page );
238251 err = sysv_prepare_chunk (page , pos , SYSV_DIRSIZE );
239- BUG_ON (err );
252+ if (err ) {
253+ unlock_page (page );
254+ return err ;
255+ }
240256 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 );
243258 inode -> i_ctime = inode -> i_mtime = current_time (inode );
244259 mark_inode_dirty (inode );
245- return err ;
260+ return sysv_handle_dirsync ( inode ) ;
246261}
247262
248263int sysv_make_empty (struct inode * inode , struct inode * dir )
@@ -259,9 +274,7 @@ int sysv_make_empty(struct inode *inode, struct inode *dir)
259274 unlock_page (page );
260275 goto fail ;
261276 }
262- kmap (page );
263-
264- base = (char * )page_address (page );
277+ base = kmap_local_page (page );
265278 memset (base , 0 , PAGE_SIZE );
266279
267280 de = (struct sysv_dir_entry * ) base ;
@@ -271,8 +284,9 @@ int sysv_make_empty(struct inode *inode, struct inode *dir)
271284 de -> inode = cpu_to_fs16 (SYSV_SB (inode -> i_sb ), dir -> i_ino );
272285 strcpy (de -> name ,".." );
273286
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 );
276290fail :
277291 put_page (page );
278292 return err ;
@@ -286,16 +300,15 @@ int sysv_empty_dir(struct inode * inode)
286300 struct super_block * sb = inode -> i_sb ;
287301 struct page * page = NULL ;
288302 unsigned long i , npages = dir_pages (inode );
303+ char * kaddr ;
289304
290305 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 ;
294307
295- if (IS_ERR (page ))
308+ kaddr = dir_get_page (inode , i , & page );
309+ if (IS_ERR (kaddr ))
296310 continue ;
297311
298- kaddr = (char * )page_address (page );
299312 de = (struct sysv_dir_entry * )kaddr ;
300313 kaddr += PAGE_SIZE - SYSV_DIRSIZE ;
301314
@@ -314,44 +327,51 @@ int sysv_empty_dir(struct inode * inode)
314327 if (de -> name [1 ] != '.' || de -> name [2 ])
315328 goto not_empty ;
316329 }
317- dir_put_page (page );
330+ dir_put_page (page , kaddr );
318331 }
319332 return 1 ;
320333
321334not_empty :
322- dir_put_page (page );
335+ dir_put_page (page , kaddr );
323336 return 0 ;
324337}
325338
326339/* 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 ,
328341 struct inode * inode )
329342{
330343 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 );
333345 int err ;
334346
335347 lock_page (page );
336348 err = sysv_prepare_chunk (page , pos , SYSV_DIRSIZE );
337- BUG_ON (err );
349+ if (err ) {
350+ unlock_page (page );
351+ return err ;
352+ }
338353 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 );
341355 dir -> i_mtime = dir -> i_ctime = current_time (dir );
342356 mark_inode_dirty (dir );
357+ return sysv_handle_dirsync (inode );
343358}
344359
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 )
346368{
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 );
349370
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 ;
355375}
356376
357377ino_t sysv_inode_by_name (struct dentry * dentry )
@@ -362,7 +382,7 @@ ino_t sysv_inode_by_name(struct dentry *dentry)
362382
363383 if (de ) {
364384 res = fs16_to_cpu (SYSV_SB (dentry -> d_sb ), de -> inode );
365- dir_put_page (page );
385+ dir_put_page (page , de );
366386 }
367387 return res ;
368388}
0 commit comments