shift BKL out of vfs_readdir
Subsystems (17)
PATCH 1/1 shift BKL out of vfs_readdir
Oh boy, here's another one. This patch takes the BKL out of vfs_readdir() and moves it into the individual filesystems, all 35 of them. I have the feeling that this wasn't done before because there are a lot of these to change and it was a pain to find them all. I definitely got all of those that were defined in the in the structure declaration like this "readdir: fs_readdir;" vxfs_readdir was assigned strangely, but I found it anyway. I also left devfs out of this one. Richard seems confident that devfs has no need for the BKL.
Anyway, patch attached. Unlike the last one, this one actually compiles :)
Signature · 2 lines
Dave Hansen [email protected]
Documentation/filesystems/Locking +1 -1
@@ -254,7 +254,7 @@ llseek: yes (see below) read: no write: no -readdir: yes (see below) +readdir: no poll: no ioctl: yes (see below) mmap: no
drivers/isdn/capi/capifs.c +7 -3
@@ -97,18 +97,20 @@off_t nr;char numbuf[32 ]; +lock_kernel (); + nr = filp->f_pos;switch (nr) {case 0 :if (filldir (dirent,"." ,1 , nr, inode->i_ino,DT_DIR ) <0 ) -return 0 ; + goto out; filp->f_pos = ++nr;/* fall through */ case 1 :if (filldir (dirent,".." ,2 , nr, inode->i_ino,DT_DIR ) <0 ) -return 0 ; + goto out; filp->f_pos = ++nr;/* fall through */ default :
@@ -120,13 +122,15 @@if (np->type) *p++ = np->type;sprintf (p,"%u" , np->num);if (filldir (dirent, numbuf,strlen (numbuf), nr, nr,DT_UNKNOWN ) <0 ) -return 0 ; + goto out; } filp->f_pos = ++nr; }break ; } +out: +unlock_kernel ();return 0 ; }
fs/adfs/dir.c +3 -0
@@ -36,6 +36,8 @@struct adfs_dir dir;int ret =0 ; +lock_kernel (); +if (filp->f_pos >>32 ) goto out;
@@ -77,6 +79,7 @@ ops->free (&dir); out: +unlock_kernel ();return ret; }
fs/affs/dir.c +4 -0
@@ -22,6 +22,7 @@#include <linux/string.h> #include <linux/mm.h> #include <linux/amigaffs.h> +#include <linux/smp_lock.h> static int affs_readdir (struct file *,void *,filldir_t );
@@ -63,6 +64,8 @@int stored;int res; +lock_kernel (); +pr_debug ("AFFS: readdir(ino=%lu,f_pos=%lx)\n" ,inode->i_ino,(unsigned long )filp->f_pos); stored =0 ;
@@ -158,6 +161,7 @@affs_brelse (dir_bh);affs_brelse (fh_bh);affs_unlock_dir (inode); +unlock_kernel ();pr_debug ("AFFS: readdir()=%d\n" , stored);return res; }
fs/autofs/root.c +7 -3
@@ -47,6 +47,8 @@struct inode * inode = filp->f_dentry->d_inode;off_t onr, nr; +lock_kernel (); + sbi =autofs_sbi (inode->i_sb); dirhash = &sbi->dirhash; nr = filp->f_pos;
@@ -55,25 +57,27 @@ {case 0 :if (filldir (dirent,"." ,1 , nr, inode->i_ino,DT_DIR ) <0 ) -return 0 ; + goto out; filp->f_pos = ++nr;/* fall through */ case 1 :if (filldir (dirent,".." ,2 , nr, inode->i_ino,DT_DIR ) <0 ) -return 0 ; + goto out; filp->f_pos = ++nr;/* fall through */ default :while ( onr = nr, ent =autofs_hash_enum (dirhash,&nr,ent) ) {if ( !ent->dentry ||d_mountpoint (ent->dentry) ) {if (filldir (dirent,ent->name,ent->len,onr,ent->ino,DT_UNKNOWN ) <0 ) -return 0 ; + goto out; filp->f_pos = nr; } }break ; } +out: +unlock_kernel ();return 0 ; }
fs/bad_inode.c +1 -0
@@ -9,6 +9,7 @@#include <linux/fs.h> #include <linux/stat.h> #include <linux/time.h> +#include <linux/smp_lock.h> /* * The follow_link operation is special: it must behave as a no-op
fs/bfs/dir.c +5 -0
@@ -32,9 +32,12 @@unsigned int offset;int block; +lock_kernel (); +if (f->f_pos & (BFS_DIRENT_SIZE -1 )) {printf ("Bad f_pos=%08lx for %s:%08lx\n" , (unsigned long )f->f_pos, dir->i_sb->s_id, dir->i_ino); +unlock_kernel ();return -EBADF ; }
@@ -52,6 +55,7 @@int size =strnlen (de->name,BFS_NAMELEN );if (filldir (dirent, de->name, size, f->f_pos, de->ino,DT_UNKNOWN ) <0 ) {brelse (bh); +unlock_kernel ();return 0 ; } }
@@ -62,6 +66,7 @@ }UPDATE_ATIME (dir); +unlock_kernel ();return 0 ; }
fs/cramfs/inode.c +6 -1
@@ -293,6 +293,8 @@if (offset &3 )return -EINVAL ; +lock_kernel (); + copied =0 ;while (offset < inode->i_size) {struct cramfs_inode *de;
@@ -313,8 +315,10 @@ namelen = de->namelen <<2 ; nextoffset = offset +sizeof (*de) + namelen;for (;;) { -if (!namelen) +if (!namelen) { +unlock_kernel ();return -EIO ; + }if (name[namelen-1 ])break ; namelen--;
@@ -327,6 +331,7 @@ filp->f_pos = offset; copied++; } +unlock_kernel ();return 0 ; }
fs/devpts/root.c +7 -3
@@ -48,18 +48,20 @@off_t nr;char numbuf[16 ]; +lock_kernel (); + nr = filp->f_pos;switch (nr) {case 0 :if (filldir (dirent,"." ,1 , nr, inode->i_ino,DT_DIR ) <0 ) -return 0 ; + goto out; filp->f_pos = ++nr;/* fall through */ case 1 :if (filldir (dirent,".." ,2 , nr, inode->i_ino,DT_DIR ) <0 ) -return 0 ; + goto out; filp->f_pos = ++nr;/* fall through */ default :
@@ -68,13 +70,15 @@if ( sbi->inodes[ptynr] ) {genptsname (numbuf, ptynr);if (filldir (dirent, numbuf,strlen (numbuf), nr, nr,DT_CHR ) <0 ) -return 0 ; + goto out; } filp->f_pos = ++nr; }break ; } +out: +unlock_kernel ();return 0 ; }
fs/efs/dir.c +6 -1
@@ -5,6 +5,7 @@*/ #include <linux/efs_fs.h> +#include <linux/smp_lock.h> static int efs_readdir (struct file *,void *,filldir_t );
@@ -31,6 +32,8 @@if (inode->i_size & (EFS_DIRBSIZE -1 ))printk (KERN_WARNING "EFS: WARNING: readdir(): directory size not a multiple of EFS_DIRBSIZE\n" ); +lock_kernel (); +/* work out where this entry can be found */ block = filp->f_pos >>EFS_DIRBSIZE_BITS ;
@@ -91,7 +94,7 @@ }brelse (bh); filp->f_pos = (block <<EFS_DIRBSIZE_BITS ) | slot; -return 0 ; + goto out; } slot++; }
@@ -102,6 +105,8 @@ } filp->f_pos = (block <<EFS_DIRBSIZE_BITS ) | slot; +out: +unlock_kernel ();return 0 ; }
fs/ext2/dir.c +4 -0
@@ -23,6 +23,7 @@#include "ext2.h" #include <linux/pagemap.h> +#include <linux/smp_lock.h> typedef struct ext2_dir_entry_2 ext2_dirent ;
@@ -246,6 +247,8 @@unsigned char *types =NULL ;int need_revalidate = (filp->f_version != inode->i_version); +lock_kernel (); +if (pos > inode->i_size -EXT2_DIR_REC_LEN (1 )) goto done;
@@ -290,6 +293,7 @@ filp->f_pos = (n <<PAGE_CACHE_SHIFT ) | offset; filp->f_version = inode->i_version;UPDATE_ATIME (inode); +unlock_kernel ();return 0 ; }
fs/ext3/dir.c +6 -1
@@ -21,6 +21,7 @@#include <linux/fs.h> #include <linux/jbd.h> #include <linux/ext3_fs.h> +#include <linux/smp_lock.h> static unsigned char ext3_filetype_table[] = {DT_UNKNOWN ,DT_REG ,DT_DIR ,DT_CHR ,DT_BLK ,DT_FIFO ,DT_SOCK ,DT_LNK
@@ -30,7 +31,7 @@struct file_operations ext3_dir_operations = { read: generic_read_dir, - readdir: ext3_readdir,/* BKL held */ + readdir: ext3_readdir,/* we take BKL. needed?*/ ioctl: ext3_ioctl,/* BKL held */ fsync: ext3_sync_file,/* BKL held */ };
@@ -77,6 +78,8 @@int err;struct inode *inode = filp->f_dentry->d_inode; +lock_kernel (); + sb = inode->i_sb; stored =0 ;
@@ -150,6 +153,7 @@ filp->f_pos = (filp->f_pos | (sb->s_blocksize -1 )) +1 ;brelse (bh); +unlock_kernel ();return stored; } offset +=le16_to_cpu (de->rec_len);
@@ -186,5 +190,6 @@brelse (bh); }UPDATE_ATIME (inode); +unlock_kernel ();return 0 ; }
fs/fat/dir.c +14 -5
@@ -17,6 +17,7 @@#include <linux/time.h> #include <linux/msdos_fs.h> #include <linux/dirent.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h>
@@ -363,13 +364,16 @@unsigned short opt_shortname =MSDOS_SB (sb)->options.shortname;int ino, inum, chi, chl, i, i2, j, last, last_u, dotoffset =0 ;loff_t cpos; +int ret =0 ; + +lock_kernel (); cpos = filp->f_pos;/* Fake . and .. for the root directory. */ if (inode->i_ino ==MSDOS_ROOT_INO ) {while (cpos <2 ) {if (filldir (dirent,".." , cpos+1 , cpos,MSDOS_ROOT_INO ,DT_DIR ) <0 ) -return 0 ; + goto out; cpos++; filp->f_pos++; }
@@ -379,8 +383,10 @@ cpos =0 ; } } -if (cpos & (sizeof (struct msdos_dir_entry )-1 )) -return -ENOENT ; +if (cpos & (sizeof (struct msdos_dir_entry )-1 )) { + ret = -ENOENT ; + goto out; + } bh =NULL ; GetNew:
@@ -414,7 +420,8 @@if (!unicode) { filp->f_pos = cpos;fat_brelse (sb, bh); -return -ENOMEM ; + ret = -ENOMEM ; + goto out; } } ParseLong:
@@ -580,7 +587,9 @@if (unicode) {free_page ((unsigned long ) unicode); } -return 0 ; +out: +unlock_kernel (); +return ret; }int fat_readdir (struct file *filp,void *dirent,filldir_t filldir)
fs/freevxfs/vxfs_lookup.c +4 -1
@@ -262,8 +262,10 @@ pos = fp->f_pos -2 ; -if (pos >VXFS_DIRROUND (ip->i_size)) +if (pos >VXFS_DIRROUND (ip->i_size)) { +unlock_kernel ();return 0 ; + } npages =dir_pages (ip); nblocks =dir_blocks (ip);
@@ -322,5 +324,6 @@ done: fp->f_pos = ((page <<PAGE_CACHE_SHIFT ) | offset) +2 ; out: +unlock_kernel ();return 0 ; }
fs/hfs/dir_cap.c +12 -8
@@ -188,6 +188,8 @@struct hfs_cat_entry *entry;struct inode *dir = filp->f_dentry->d_inode; +lock_kernel (); + entry =HFS_I (dir)->entry; type =HFS_ITYPE (dir->i_ino); skip_dirs = (type ==HFS_CAP_RDIR );
@@ -195,7 +197,7 @@if (filp->f_pos ==0 ) {/* Entry 0 is for "." */ if (filldir (dirent,DOT ->Name,DOT_LEN ,0 , dir->i_ino,DT_DIR )) { -return 0 ; + goto out; } filp->f_pos =1 ; }
@@ -212,7 +214,7 @@if (filldir (dirent,DOT_DOT ->Name,DOT_DOT_LEN ,1 ,ntohl (cnid),DT_DIR )) { -return 0 ; + goto out; } filp->f_pos =2 ; }
@@ -223,11 +225,11 @@if (hfs_cat_open (entry, &brec) ||hfs_cat_next (entry, &brec, filp->f_pos -2 , &cnid, &type)) { -return 0 ; + goto out; }while (filp->f_pos < (dir->i_size -3 )) {if (hfs_cat_next (entry, &brec,1 , &cnid, &type)) { -return 0 ; + goto out; }if (!skip_dirs || (type !=HFS_CDR_DIR )) {ino_t ino;
@@ -240,7 +242,7 @@if (filldir (dirent, tmp_name, len, filp->f_pos, ino,DT_UNKNOWN )) {hfs_cat_close (entry, &brec); -return 0 ; + goto out; } } ++filp->f_pos;
@@ -256,7 +258,7 @@ DOT_ROOTINFO_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_CAP_FNDR, DT_UNKNOWN)) { -return 0 ; + goto out; } } ++filp->f_pos;
@@ -269,7 +271,7 @@ DOT_FINDERINFO_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_CAP_FDIR, DT_UNKNOWN)) { -return 0 ; + goto out; } } ++filp->f_pos;
@@ -282,12 +284,14 @@ DOT_RESOURCE_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_CAP_RDIR, DT_UNKNOWN)) { -return 0 ; + goto out; } } ++filp->f_pos; } +out: +unlock_kernel ();return 0 ; }
fs/hfs/dir_dbl.c +10 -6
@@ -182,13 +182,15 @@struct hfs_cat_entry *entry;struct inode *dir = filp->f_dentry->d_inode; +lock_kernel (); + entry =HFS_I (dir)->entry;if (filp->f_pos ==0 ) {/* Entry 0 is for "." */ if (filldir (dirent,DOT ->Name,DOT_LEN ,0 , dir->i_ino,DT_DIR )) { -return 0 ; + goto out; } filp->f_pos =1 ; }
@@ -197,7 +199,7 @@/* Entry 1 is for ".." */ if (filldir (dirent,DOT_DOT ->Name,DOT_DOT_LEN ,1 ,hfs_get_hl (entry->key.ParID),DT_DIR )) { -return 0 ; + goto out; } filp->f_pos =2 ; }
@@ -209,7 +211,7 @@if (hfs_cat_open (entry, &brec) ||hfs_cat_next (entry, &brec, (filp->f_pos -1 ) >>1 , &cnid, &type)) { -return 0 ; + goto out; }while (filp->f_pos < (dir->i_size -1 )) {
@@ -226,7 +228,7 @@ }else {if (hfs_cat_next (entry, &brec,1 , &cnid, &type)) { -return 0 ; + goto out; } ino =ntohl (cnid); len = hfs_namein(dir, tmp_name,
@@ -236,7 +238,7 @@if (filldir (dirent, tmp_name, len, filp->f_pos, ino,DT_UNKNOWN )) {hfs_cat_close (entry, &brec); -return 0 ; + goto out; } ++filp->f_pos; }
@@ -250,12 +252,14 @@ PCNT_ROOTINFO_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_DBL_HDR, DT_UNKNOWN)) { -return 0 ; + goto out; } } ++filp->f_pos; } +out: +unlock_kernel ();return 0 ; }
fs/hfs/dir_nat.c +12 -8
@@ -188,6 +188,8 @@struct hfs_cat_entry *entry;struct inode *dir = filp->f_dentry->d_inode; +lock_kernel (); + entry =HFS_I (dir)->entry; type =HFS_ITYPE (dir->i_ino); skip_dirs = (type ==HFS_NAT_HDIR );
@@ -196,7 +198,7 @@/* Entry 0 is for "." */ if (filldir (dirent,DOT ->Name,DOT_LEN ,0 , dir->i_ino,DT_DIR )) { -return 0 ; + goto out; } filp->f_pos =1 ; }
@@ -213,7 +215,7 @@if (filldir (dirent,DOT_DOT ->Name,DOT_DOT_LEN ,1 ,ntohl (cnid),DT_DIR )) { -return 0 ; + goto out; } filp->f_pos =2 ; }
@@ -224,11 +226,11 @@if (hfs_cat_open (entry, &brec) ||hfs_cat_next (entry, &brec, filp->f_pos -2 , &cnid, &type)) { -return 0 ; + goto out; }while (filp->f_pos < (dir->i_size -2 )) {if (hfs_cat_next (entry, &brec,1 , &cnid, &type)) { -return 0 ; + goto out; }if (!skip_dirs || (type !=HFS_CDR_DIR )) {ino_t ino;
@@ -241,7 +243,7 @@if (filldir (dirent, tmp_name, len, filp->f_pos, ino,DT_UNKNOWN )) {hfs_cat_close (entry, &brec); -return 0 ; + goto out; } } ++filp->f_pos;
@@ -256,7 +258,7 @@ DOT_APPLEDOUBLE_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_NAT_HDIR, DT_UNKNOWN)) { -return 0 ; + goto out; } }else if (type ==HFS_NAT_HDIR ) {/* In .AppleDouble entry 2 is for ".Parent" */
@@ -264,7 +266,7 @@ DOT_PARENT_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_NAT_HDR, DT_UNKNOWN)) { -return 0 ; + goto out; } } ++filp->f_pos;
@@ -278,12 +280,14 @@ ROOTINFO_LEN, filp->f_pos, ntohl(entry->cnid) | HFS_NAT_HDR, DT_UNKNOWN)) { -return 0 ; + goto out; } } ++filp->f_pos; } +out: +unlock_kernel ();return 0 ; }
fs/hpfs/dir.c +36 -17
120 lines not on this page · raw message
fs/isofs/dir.c +4 -0
@@ -21,6 +21,7 @@#include <linux/time.h> #include <linux/locks.h> #include <linux/config.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h>
@@ -253,6 +254,8 @@struct iso_directory_record * tmpde;struct inode *inode = filp->f_dentry->d_inode; +lock_kernel (); + tmpname = (char *)__get_free_page (GFP_KERNEL );if (!tmpname)return -ENOMEM ;
@@ -261,5 +264,6 @@ result =do_isofs_readdir (inode, filp, dirent, filldir, tmpname, tmpde);free_page ((unsigned long ) tmpname); +unlock_kernel ();return result; }
fs/jffs/inode-v23.c +6 -0
@@ -48,6 +48,7 @@#include <linux/stat.h> #include <linux/blkdev.h> #include <linux/quotaops.h> +#include <linux/smp_lock.h> #include <asm/semaphore.h> #include <asm/byteorder.h> #include <asm/uaccess.h>
@@ -568,6 +569,7 @@struct jffs_control *c = (struct jffs_control *)inode->i_sb->u.generic_sbp;int j;int ddino; +lock_kernel ();D3 (printk (KERN_NOTICE "readdir(): down biglock\n" ));down (&c->fmc->biglock);
@@ -577,6 +579,7 @@if (filldir (dirent,"." ,1 , filp->f_pos, inode->i_ino,DT_DIR ) <0 ) {D3 (printk (KERN_NOTICE "readdir(): up biglock\n" ));up (&c->fmc->biglock); +unlock_kernel ();return 0 ; } filp->f_pos =1 ;
@@ -593,6 +596,7 @@if (filldir (dirent,".." ,2 , filp->f_pos, ddino,DT_DIR ) <0 ) {D3 (printk (KERN_NOTICE "readdir(): up biglock\n" ));up (&c->fmc->biglock); +unlock_kernel ();return 0 ; } filp->f_pos++;
@@ -611,6 +615,7 @@ filp->f_pos , f->ino, DT_UNKNOWN) < 0) {D3 (printk (KERN_NOTICE "readdir(): up biglock\n" ));up (&c->fmc->biglock); +unlock_kernel ();return 0 ; } filp->f_pos++;
@@ -620,6 +625,7 @@ }D3 (printk (KERN_NOTICE "readdir(): up biglock\n" ));up (&c->fmc->biglock); +unlock_kernel ();return filp->f_pos; }/* jffs_readdir() */
fs/jffs2/dir.c +4 -0
@@ -45,6 +45,7 @@#include <linux/jffs2_fs_i.h> #include <linux/jffs2_fs_sb.h> #include <linux/time.h> +#include <linux/smp_lock.h> #include "nodelist.h" static int jffs2_readdir (struct file *,void *,filldir_t );
@@ -143,6 +144,8 @@D1 (printk (KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n" , filp->f_dentry->d_inode->i_ino)); +lock_kernel (); + f =JFFS2_INODE_INFO (inode); c =JFFS2_SB_INFO (inode->i_sb);
@@ -186,6 +189,7 @@up (&f->sem); out: filp->f_pos = offset; +unlock_kernel ();return 0 ; }
fs/jfs/jfs_dtree.c +31 -6
@@ -102,6 +102,7 @@#include <linux/fs.h> #include <linux/locks.h> +#include <linux/smp_lock.h> #include "jfs_incore.h" #include "jfs_superblock.h" #include "jfs_filsys.h"
@@ -2868,6 +2869,8 @@if (filp->f_pos ==DIREND )return 0 ; +lock_kernel (); +if (DO_INDEX (ip)) {/* * persistent index is stored in directory entries.
@@ -2885,12 +2888,14 @@if (dtEmpty (ip)) { filp->f_pos =DIREND ; +unlock_kernel ();return 0 ; } repeat: rc =get_index (ip, dir_index, &dirtab_slot);if (rc) { filp->f_pos =DIREND ; +unlock_kernel ();return rc; }if (dirtab_slot.flag ==DIR_INDEX_FREE ) {
@@ -2898,11 +2903,13 @@jERROR (1 , ("jfs_readdir detected " "infinite loop!\n" )); filp->f_pos =DIREND ; +unlock_kernel ();return 0 ; } dir_index =le32_to_cpu (dirtab_slot.addr2);if (dir_index ==-1 ) { filp->f_pos =DIREND ; +unlock_kernel ();return 0 ; } goto repeat;
@@ -2912,12 +2919,14 @@DT_GETPAGE (ip, bn, mp,PSIZE , p, rc);if (rc) { filp->f_pos =DIREND ; +unlock_kernel ();return 0 ; }if (p->header.flag &BT_INTERNAL ) {jERROR (1 ,("jfs_readdir: bad index table\n" ));DT_PUTPAGE (mp); filp->f_pos =-1 ; +unlock_kernel ();return 0 ; } }else {
@@ -2927,27 +2936,34 @@*/ filp->f_pos =0 ;if (filldir (dirent,"." ,1 ,0 , ip->i_ino, -DT_DIR )) +DT_DIR )) { +unlock_kernel ();return 0 ; + } }/* * parent ".." */ filp->f_pos =1 ;if (filldir - (dirent,".." ,2 ,1 ,PARENT (ip),DT_DIR )) + (dirent,".." ,2 ,1 ,PARENT (ip),DT_DIR )) { +unlock_kernel ();return 0 ; + }/* * Find first entry of left-most leaf */ if (dtEmpty (ip)) { filp->f_pos =DIREND ; +unlock_kernel ();return 0 ; } -if ((rc =dtReadFirst (ip, &btstack))) +if ((rc =dtReadFirst (ip, &btstack))) { +unlock_kernel ();return -rc; + }DT_GETSEARCH (ip, btstack.top, bn, mp, p, index); }
@@ -2966,8 +2982,10 @@/* build "." entry */ if (filldir (dirent,"." ,1 , filp->f_pos, ip->i_ino, -DT_DIR )) +DT_DIR )) { +unlock_kernel ();return 0 ; + } dtoffset->index =1 ; }
@@ -2976,8 +2994,10 @@/* build ".." entry */ if (filldir (dirent,".." ,2 , filp->f_pos, -PARENT (ip),DT_DIR )) +PARENT (ip),DT_DIR )) { +unlock_kernel ();return 0 ; + } }else {jERROR (1 , ("jfs_readdir called with invalid offset!\n" ));
@@ -2988,6 +3008,7 @@if (dtEmpty (ip)) { filp->f_pos =DIREND ; +unlock_kernel ();return 0 ; }
@@ -2996,6 +3017,7 @@ ("jfs_readdir: unexpected rc = %d from dtReadNext\n" , rc)); filp->f_pos =DIREND ; +unlock_kernel ();return 0 ; }/* get start leaf page and index */
@@ -3004,6 +3026,7 @@/* offset beyond directory eof ? */ if (bn <0 ) { filp->f_pos =DIREND ; +unlock_kernel ();return 0 ; } }
@@ -3013,6 +3036,7 @@DT_PUTPAGE (mp);jERROR (1 , ("jfs_readdir: kmalloc failed!\n" )); filp->f_pos =DIREND ; +unlock_kernel ();return 0 ; }while (1 ) {
@@ -3087,6 +3111,7 @@DT_GETPAGE (ip, bn, mp,PSIZE , p, rc);if (rc) {kfree (d_name); +unlock_kernel ();return -rc; }
@@ -3102,7 +3127,7 @@ out:kfree (d_name);DT_PUTPAGE (mp); - +unlock_kernel ();return rc; }
fs/libfs.c +5 -0
@@ -4,6 +4,7 @@*/ #include <linux/pagemap.h> +#include <linux/smp_lock.h> int simple_statfs (struct super_block *sb,struct statfs *buf) {
@@ -40,6 +41,8 @@int i;struct dentry *dentry = filp->f_dentry; +lock_kernel (); + i = filp->f_pos;switch (i) {case 0 :
@@ -64,6 +67,7 @@for (;;) {if (list == &dentry->d_subdirs) {spin_unlock (&dcache_lock); +unlock_kernel ();return 0 ; }if (!j)
@@ -94,6 +98,7 @@ } } } +unlock_kernel ();return 0 ; }
fs/minix/dir.c +4 -0
@@ -7,6 +7,7 @@*/ #include "minix.h" +#include <linux/smp_lock.h> typedef struct minix_dir_entry minix_dirent ;
@@ -78,6 +79,8 @@struct minix_sb_info *sbi =minix_sb (sb);unsigned chunk_size = sbi->s_dirsize; +lock_kernel (); + pos = (pos + chunk_size-1 ) & ~(chunk_size-1 );if (pos >= inode->i_size) goto done;
@@ -113,6 +116,7 @@ done: filp->f_pos = (n <<PAGE_CACHE_SHIFT ) | offset;UPDATE_ATIME (inode); +unlock_kernel ();return 0 ; }
fs/ncpfs/dir.c +3 -0
@@ -400,6 +400,8 @@int result, mtime_valid =0 ;time_t mtime =0 ; +lock_kernel (); + ctl.page =NULL ; ctl.cache =NULL ;
@@ -533,6 +535,7 @@page_cache_release (ctl.page); } out: +unlock_kernel ();return result; }
fs/nfs/dir.c +6 -1
@@ -355,9 +355,13 @@struct nfs_entry my_entry;long res; +lock_kernel (); + res =nfs_revalidate (dentry); -if (res <0 ) +if (res <0 ) { +unlock_kernel ();return res; + }/* * filp->f_pos points to the file offset in the page cache.
@@ -394,6 +398,7 @@break ; } } +unlock_kernel ();if (desc->error <0 )return desc->error;if (res <0 )
fs/nfs/nfs3proc.c +4 -0
@@ -14,6 +14,7 @@#include <linux/nfs.h> #include <linux/nfs3.h> #include <linux/nfs_fs.h> +#include <linux/smp_lock.h> #define NFSDBG_FACILITY NFSDBG_PROC
@@ -560,6 +561,8 @@u32 *verf =NFS_COOKIEVERF (dir);int status; +lock_kernel (); + arg.buffer = entry; arg.bufsiz = size; arg.verf[0 ] = verf[0 ];
@@ -580,6 +583,7 @@ status =rpc_call_sync (NFS_CLIENT (dir), &msg,0 );nfs_refresh_inode (dir, &dir_attr);dprintk ("NFS reply readdir: %d\n" , status); +unlock_kernel ();return status; }
fs/nfs/proc.c +4 -0
@@ -41,6 +41,7 @@#include <linux/nfs.h> #include <linux/nfs2.h> #include <linux/nfs_fs.h> +#include <linux/smp_lock.h> #define NFSDBG_FACILITY NFSDBG_PROC
@@ -440,6 +441,8 @@ };int status; +lock_kernel (); + arg.fh =NFS_FH (dir); arg.cookie = cookie; arg.buffer = entry;
@@ -451,6 +454,7 @@ status =rpc_call_sync (NFS_CLIENT (dir), &msg,0 );dprintk ("NFS reply readdir: %d\n" , status); +unlock_kernel ();return status; }
fs/ntfs/fs.c +4 -0
@@ -250,6 +250,8 @@int err;struct ntfs_filldir cb; +lock_kernel (); + cb.ret_code =0 ; cb.pl = filp->f_pos &0xffff ; cb.ph = (filp->f_pos >>16 ) &0x7fff ;
@@ -312,10 +314,12 @@"returned %i, returning 0, f_pos " "0x%Lx.\n", cb.ret_code, filp->f_pos);#endif +unlock_kernel ();return 0 ; }ntfs_debug (DEBUG_OTHER , __FUNCTION__"(): Returning %i, f_pos 0x%Lx.\n" , err, filp->f_pos); +unlock_kernel ();return err; }
fs/openpromfs/inode.c +11 -7
@@ -756,12 +756,14 @@u16 node;char *p;char buffer2[64 ]; + +lock_kernel (); ino = inode->i_ino; i = filp->f_pos;switch (i) {case 0 : -if (filldir (dirent,"." ,1 , i, ino,DT_DIR ) <0 )return 0 ; +if (filldir (dirent,"." ,1 , i, ino,DT_DIR ) <0 ) goto out; i++; filp->f_pos++;/* fall thru */
@@ -769,7 +771,7 @@if (filldir (dirent,".." ,2 , i, (NODE (ino).parent ==0xffff ) ?OPENPROM_ROOT_INO :NODE2INO (NODE (ino).parent),DT_DIR ) <0 ) -return 0 ; + goto out; i++; filp->f_pos++;/* fall thru */
@@ -782,17 +784,17 @@ }while (node !=0xffff ) {if (prom_getname (nodes[node].node, buffer,128 ) <0 ) -return 0 ; + goto out;if (filldir (dirent, buffer,strlen (buffer), filp->f_pos,NODE2INO (node),DT_DIR ) <0 ) -return 0 ; + goto out; filp->f_pos++; node = nodes[node].next; } j =NODEP2INO (NODE (ino).first_prop);if (!i) {if (filldir (dirent,".node" ,5 , filp->f_pos, j,DT_REG ) <0 ) -return 0 ; + goto out; filp->f_pos++; }else i--;
@@ -802,7 +804,7 @@if (alias_names [i]) {if (filldir (dirent, alias_names [i],strlen (alias_names [i]), - filp->f_pos, j,DT_REG ) <0 )return 0 ; + filp->f_pos, j,DT_REG ) <0 ) goto out; filp->f_pos++; } }
@@ -815,12 +817,14 @@else {if (filldir (dirent, p,strlen (p), filp->f_pos, j,DT_REG ) <0 ) -return 0 ; + goto out; filp->f_pos++; } } } } +out: +unlock_kernel ();return 0 ; }
fs/proc/base.c +23 -8
@@ -26,6 +26,7 @@#include <linux/seq_file.h> #include <linux/namespace.h> #include <linux/mm.h> +#include <linux/smp_lock.h> /* * For hysterical raisins we keep the same inumbers as in the old procfs.
@@ -571,6 +572,8 @@struct dentry *de;struct vfsmount *mnt =NULL ; +lock_kernel (); +if (current->fsuid != inode->i_uid && !capable (CAP_DAC_OVERRIDE )) goto out; error =proc_check_root (inode);
@@ -585,6 +588,7 @@dput (de);mntput (mnt); out: +unlock_kernel ();return error; }
@@ -665,38 +669,49 @@int pid;struct inode *inode = filp->f_dentry->d_inode;struct pid_entry *p; +int ret =0 ; + +lock_kernel (); pid =proc_task (inode)->pid; -if (!pid) -return -ENOENT ; +if (!pid) { + ret = -ENOENT ; + goto out; + } i = filp->f_pos;switch (i) {case 0 :if (filldir (dirent,"." ,1 , i, inode->i_ino,DT_DIR ) <0 ) -return 0 ; + goto out; i++; filp->f_pos++;/* fall through */ case 1 :if (filldir (dirent,".." ,2 , i,PROC_ROOT_INO ,DT_DIR ) <0 ) -return 0 ; + goto out; i++; filp->f_pos++;/* fall through */ default : i -=2 ; -if (i>=sizeof (base_stuff)/sizeof (base_stuff[0 ])) -return 1 ; +if (i>=sizeof (base_stuff)/sizeof (base_stuff[0 ])) { + ret =1 ; + goto out; + } p = base_stuff + i;while (p->name) {if (filldir (dirent, p->name, p->len, filp->f_pos,fake_ino (pid, p->type), p->mode >>12 ) <0 ) -return 0 ; + goto out; filp->f_pos++; p++; } } -return 1 ; + + ret =1 ; +out: +unlock_kernel (); +return ret; }/* building an inode */
fs/proc/generic.c +17 -8
@@ -304,16 +304,21 @@unsigned int ino;int i;struct inode *inode = filp->f_dentry->d_inode; +int ret =0 ; + +lock_kernel (); ino = inode->i_ino; de =PDE (inode); -if (!de) -return -EINVAL ; +if (!de) { + ret = -EINVAL ; + goto out; + } i = filp->f_pos;switch (i) {case 0 :if (filldir (dirent,"." ,1 , i, ino,DT_DIR ) <0 ) -return 0 ; + goto out; i++; filp->f_pos++;/* fall through */
@@ -321,7 +326,7 @@if (filldir (dirent,".." ,2 , i,parent_ino (filp->f_dentry),DT_DIR ) <0 ) -return 0 ; + goto out; i++; filp->f_pos++;/* fall through */
@@ -329,8 +334,10 @@ de = de->subdir; i -=2 ;for (;;) { -if (!de) -return 1 ; +if (!de) { + ret =1 ; + goto out; + }if (!i)break ; de = de->next;
@@ -340,12 +347,14 @@do {if (filldir (dirent, de->name, de->namelen, filp->f_pos, de->low_ino, de->mode >>12 ) <0 ) -return 0 ; + goto out; filp->f_pos++; de = de->next; }while (de); } -return 1 ; + ret =1 ; +out:unlock_kernel (); +return ret; }/*
fs/proc/root.c +9 -2
@@ -98,15 +98,22 @@ void * dirent, filldir_t filldir) {unsigned int nr = filp->f_pos; +int ret; + +lock_kernel ();if (nr <FIRST_PROCESS_ENTRY ) {int error =proc_readdir (filp, dirent, filldir); -if (error <=0 ) +if (error <=0 ) { +unlock_kernel ();return error; + } filp->f_pos =FIRST_PROCESS_ENTRY ; } -return proc_pid_readdir (filp, dirent, filldir); + ret =proc_pid_readdir (filp, dirent, filldir); +unlock_kernel (); +return ret; }/*
fs/qnx4/dir.c +6 -1
@@ -17,6 +17,7 @@#include <linux/fs.h> #include <linux/qnx4_fs.h> #include <linux/stat.h> +#include <linux/smp_lock.h> static int qnx4_readdir (struct file *filp,void *dirent,filldir_t filldir)
@@ -33,6 +34,8 @@QNX4DEBUG (("qnx4_readdir:i_size = %ld\n" , (long ) inode->i_size));QNX4DEBUG (("filp->f_pos = %ld\n" , (long ) filp->f_pos)); +lock_kernel (); +while (filp->f_pos < inode->i_size) { blknum =qnx4_block_map ( inode, filp->f_pos >>QNX4_BLOCK_SIZE_BITS ); bh =sb_bread (inode->i_sb, blknum);
@@ -63,7 +66,7 @@ }if (filldir (dirent, de->di_fname, size, filp->f_pos, ino,DT_UNKNOWN ) <0 ) {brelse (bh); -return 0 ; + goto out; } } }
@@ -74,6 +77,8 @@ }UPDATE_ATIME (inode); +out: +unlock_kernel ();return 0 ; }
fs/readdir.c +0 -2
@@ -23,9 +23,7 @@down (&inode->i_sem); res = -ENOENT ;if (!IS_DEADDIR (inode)) { -lock_kernel (); res = file->f_op->readdir (file, buf, filler); -unlock_kernel (); }up (&inode->i_sem); out:
fs/reiserfs/dir.c +9 -3
@@ -47,7 +47,9 @@loff_t next_pos;char small_buf[32 ] ;/* avoid kmalloc if we can */ struct reiserfs_dir_entry de; +int ret =0 ; +lock_kernel ();reiserfs_check_lock_depth ("readdir" ) ;
@@ -66,7 +68,8 @@if (search_res ==IO_ERROR ) {// FIXME: we could just skip part of directory which could // not be read -return -EIO ; + ret = -EIO ; + goto out; } entry_num = de.de_entry_num; bh = de.de_bh;
@@ -118,7 +121,8 @@ local_buf =reiserfs_kmalloc (d_reclen,GFP_NOFS , inode->i_sb) ;if (!local_buf) {pathrelse (&path_to_entry); -return -ENOMEM ; + ret = -ENOMEM ; + goto out; }if (item_moved (&tmp_ih, &path_to_entry)) {reiserfs_kfree (local_buf, d_reclen, inode->i_sb) ;
@@ -181,7 +185,9 @@pathrelse (&path_to_entry);reiserfs_check_path (&path_to_entry) ;UPDATE_ATIME (inode) ; -return 0 ; + out: +unlock_kernel (); +return ret; }/* compose directory item containing "." and ".." entries (entries are
fs/romfs/inode.c +10 -5
@@ -273,13 +273,15 @@int stored =0 ;char fsname[ROMFS_MAXFN ];/* XXX dynamic? */ +lock_kernel (); + maxoff = i->i_sb->u.romfs_sb.s_maxsize; offset = filp->f_pos;if (!offset) { offset = i->i_ino &ROMFH_MASK ;if (romfs_copyfrom (i, &ri, offset,ROMFH_SIZE ) <=0 ) -return stored; + goto out; offset =ntohl (ri.spec) &ROMFH_MASK ; }
@@ -288,17 +290,17 @@if (!offset || offset >= maxoff) { offset = maxoff; filp->f_pos = offset; -return stored; + goto out; } filp->f_pos = offset;/* Fetch inode info */ if (romfs_copyfrom (i, &ri, offset,ROMFH_SIZE ) <=0 ) -return stored; + goto out; j =romfs_strnlen (i, offset+ROMFH_SIZE ,sizeof (fsname)-1 );if (j <0 ) -return stored; + goto out; fsname[j]=0 ;romfs_copyfrom (i, fsname, offset+ROMFH_SIZE , j);
@@ -309,11 +311,14 @@ ino =ntohl (ri.spec);if (filldir (dirent, fsname, j, offset, ino, romfs_dtype_table[nextfh &ROMFH_TYPE ]) <0 ) { -return stored; + goto out; } stored++; offset = nextfh &ROMFH_MASK ; } +out: +unlock_kernel (); +return stored; } static struct dentry *
fs/smbfs/dir.c +4 -0
@@ -75,6 +75,9 @@ DENTRY_PATH(dentry), (int) filp->f_pos); result =0 ; + +lock_kernel (); +switch ((unsigned int ) filp->f_pos) {case 0 :if (filldir (dirent,"." ,1 ,0 , dir->i_ino,DT_DIR ) <0 )
@@ -207,6 +210,7 @@page_cache_release (ctl.page); } out: +unlock_kernel ();return result; }
fs/smbfs/proc.c +7 -0
@@ -17,6 +17,7 @@#include <linux/dcache.h> #include <linux/dirent.h> #include <linux/nls.h> +#include <linux/smp_lock.h> #include <linux/smb_fs.h> #include <linux/smbno.h>
@@ -1906,6 +1907,8 @@VERBOSE ("%s/%s\n" ,DENTRY_PATH (dir)); +lock_kernel (); +smb_lock_server (server); first =1 ;
@@ -2012,6 +2015,7 @@ unlock_return:smb_unlock_server (server); +unlock_kernel ();return result; }
@@ -2172,6 +2176,8 @@ len:1 , }; +lock_kernel (); +/* * use info level 1 for older servers that don't do 260 */
@@ -2357,6 +2363,7 @@ unlock_return:smb_unlock_server (server); +unlock_kernel ();return result; }
fs/sysv/dir.c +4 -0
@@ -16,6 +16,7 @@#include <linux/fs.h> #include <linux/sysv_fs.h> #include <linux/pagemap.h> +#include <linux/smp_lock.h> static int sysv_readdir (struct file *,void *,filldir_t );
@@ -79,6 +80,8 @@unsigned long n = pos >>PAGE_CACHE_SHIFT ;unsigned long npages =dir_pages (inode); +lock_kernel (); + pos = (pos +SYSV_DIRSIZE -1 ) & ~(SYSV_DIRSIZE -1 );if (pos >= inode->i_size) goto done;
@@ -116,6 +119,7 @@ done: filp->f_pos = (n <<PAGE_CACHE_SHIFT ) | offset;UPDATE_ATIME (inode); +unlock_kernel ();return 0 ; }
fs/udf/dir.c +7 -1
@@ -35,6 +35,7 @@#include <linux/errno.h> #include <linux/mm.h> #include <linux/slab.h> +#include <linux/smp_lock.h> #include "udf_i.h" #include "udf_sb.h"
@@ -83,15 +84,20 @@struct inode *dir = filp->f_dentry->d_inode;int result; +lock_kernel (); +if ( filp->f_pos ==0 ) { -if (filldir (dirent,"." ,1 , filp->f_pos, dir->i_ino,DT_DIR ) <0 ) +if (filldir (dirent,"." ,1 , filp->f_pos, dir->i_ino,DT_DIR ) <0 ) { +unlock_kernel ();return 0 ; + } filp->f_pos ++; } result =do_udf_readdir (dir, filp, filldir, dirent);UPDATE_ATIME (dir); +unlock_kernel ();return result; }
fs/ufs/dir.c +6 -0
@@ -17,6 +17,7 @@#include <linux/locks.h> #include <linux/fs.h> #include <linux/ufs_fs.h> +#include <linux/smp_lock.h> #include "swab.h" #include "util.h"
@@ -62,6 +63,8 @@int de_reclen;unsigned flags; +lock_kernel (); + sb = inode->i_sb; flags = sb->u.ufs_sb.s_flags;
@@ -117,6 +120,7 @@ (sb->s_blocksize - 1)) + sb->s_blocksize;brelse (bh); +unlock_kernel ();return stored; } if (!ufs_check_dir_entry ("ufs_readdir", inode, de,
@@ -127,6 +131,7 @@ (sb->s_blocksize - 1)) +1 ;brelse (bh); +unlock_kernel ();return stored; } offset +=fs16_to_cpu (sb, de->d_reclen);
@@ -161,6 +166,7 @@brelse (bh); }UPDATE_ATIME (inode); +unlock_kernel ();return 0 ; }
fs/umsdos/dir.c +4 -0
@@ -17,6 +17,7 @@#include <linux/umsdos_fs.h> #include <linux/slab.h> #include <linux/pagemap.h> +#include <linux/smp_lock.h> #define UMSDOS_SPECIAL_DIRFPOS 3extern struct dentry *saved_root;
@@ -302,6 +303,8 @@int ret =0 , count =0 ;struct UMSDOS_DIR_ONCE bufk; +lock_kernel (); + bufk.dirbuf = dirbuf; bufk.filldir = filldir; bufk.stop =0 ;
@@ -317,6 +320,7 @@break ; count += bufk.count; } +unlock_kernel ();Printk (("UMSDOS_readdir out %d count %d pos %Ld\n" , ret, count, filp->f_pos));return count ? : ret;
fs/umsdos/rdir.c +6 -1
@@ -15,6 +15,7 @@#include <linux/limits.h> #include <linux/umsdos_fs.h> #include <linux/slab.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h>
@@ -63,11 +64,15 @@ {struct inode *dir = filp->f_dentry->d_inode;struct RDIR_FILLDIR bufk; +int ret; +lock_kernel (); bufk.filldir = filldir; bufk.dirbuf = dirbuf; bufk.real_root = pseudo_root && (dir == saved_root->d_inode); -return fat_readdir (filp, &bufk, rdir_filldir); + ret =fat_readdir (filp, &bufk, rdir_filldir); +unlock_kernel (); +return ret; }