]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/namei.c
procfs: speed up /proc/pid/stat, statm
[karo-tx-linux.git] / fs / namei.c
index fa96a26d329101e243273255803e4ea4c0592c02..73ec863a9896dad4f50f0bbeb1e9aa82558f6e04 100644 (file)
@@ -161,7 +161,7 @@ static char *getname_flags(const char __user *filename, int flags, int *empty)
 
 char *getname(const char __user * filename)
 {
-       return getname_flags(filename, 0, 0);
+       return getname_flags(filename, 0, NULL);
 }
 
 #ifdef CONFIG_AUDITSYSCALL
@@ -642,7 +642,7 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
        cond_resched();
        current->total_link_count++;
 
-       touch_atime(link->mnt, dentry);
+       touch_atime(link);
        nd_set_link(nd, NULL);
 
        error = security_inode_follow_link(link->dentry, nd);
@@ -1408,7 +1408,7 @@ static inline int can_lookup(struct inode *inode)
  */
 static inline long count_masked_bytes(unsigned long mask)
 {
-       return mask*0x0001020304050608 >> 56;
+       return mask*0x0001020304050608ul >> 56;
 }
 
 static inline unsigned int fold_hash(unsigned long hash)
@@ -1439,10 +1439,10 @@ unsigned int full_name_hash(const unsigned char *name, unsigned int len)
 
        for (;;) {
                a = *(unsigned long *)name;
-               hash *= 9;
                if (len < sizeof(unsigned long))
                        break;
                hash += a;
+               hash *= 9;
                name += sizeof(unsigned long);
                len -= sizeof(unsigned long);
                if (!len)
@@ -1455,9 +1455,10 @@ done:
 }
 EXPORT_SYMBOL(full_name_hash);
 
-#define ONEBYTES       0x0101010101010101ul
-#define SLASHBYTES     0x2f2f2f2f2f2f2f2ful
-#define HIGHBITS       0x8080808080808080ul
+#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
+#define ONEBYTES       REPEAT_BYTE(0x01)
+#define SLASHBYTES     REPEAT_BYTE('/')
+#define HIGHBITS       REPEAT_BYTE(0x80)
 
 /* Return the high bit set in the first byte that is a zero */
 static inline unsigned long has_zero(unsigned long a)
@@ -1971,7 +1972,7 @@ int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
 int user_path_at(int dfd, const char __user *name, unsigned flags,
                 struct path *path)
 {
-       return user_path_at_empty(dfd, name, flags, path, 0);
+       return user_path_at_empty(dfd, name, flags, path, NULL);
 }
 
 static int user_path_parent(int dfd, const char __user *path,
@@ -2691,6 +2692,7 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d
 int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
        int error = may_create(dir, dentry);
+       unsigned max_links = dir->i_sb->s_max_links;
 
        if (error)
                return error;
@@ -2703,6 +2705,9 @@ int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        if (error)
                return error;
 
+       if (max_links && dir->i_nlink >= max_links)
+               return -EMLINK;
+
        error = dir->i_op->mkdir(dir, dentry, mode);
        if (!error)
                fsnotify_mkdir(dir, dentry);
@@ -3033,6 +3038,7 @@ SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newn
 int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
 {
        struct inode *inode = old_dentry->d_inode;
+       unsigned max_links = dir->i_sb->s_max_links;
        int error;
 
        if (!inode)
@@ -3063,6 +3069,8 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
        /* Make sure we don't allow creating hardlink to an unlinked file */
        if (inode->i_nlink == 0)
                error =  -ENOENT;
+       else if (max_links && inode->i_nlink >= max_links)
+               error = -EMLINK;
        else
                error = dir->i_op->link(old_dentry, dir, new_dentry);
        mutex_unlock(&inode->i_mutex);
@@ -3172,6 +3180,7 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
 {
        int error = 0;
        struct inode *target = new_dentry->d_inode;
+       unsigned max_links = new_dir->i_sb->s_max_links;
 
        /*
         * If we are going to change the parent - check write permissions,
@@ -3195,6 +3204,11 @@ static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
        if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry))
                goto out;
 
+       error = -EMLINK;
+       if (max_links && !target && new_dir != old_dir &&
+           new_dir->i_nlink >= max_links)
+               goto out;
+
        if (target)
                shrink_dcache_parent(new_dentry);
        error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
@@ -3493,9 +3507,9 @@ retry:
        if (err)
                goto fail;
 
-       kaddr = kmap_atomic(page, KM_USER0);
+       kaddr = kmap_atomic(page);
        memcpy(kaddr, symname, len-1);
-       kunmap_atomic(kaddr, KM_USER0);
+       kunmap_atomic(kaddr);
 
        err = pagecache_write_end(NULL, mapping, 0, len-1, len-1,
                                                        page, fsdata);