diff options
| -rw-r--r-- | fs/inode.c | 1 | ||||
| -rw-r--r-- | fs/namei.c | 76 | ||||
| -rw-r--r-- | fs/stat.c | 4 | ||||
| -rw-r--r-- | include/linux/fs.h | 59 |
4 files changed, 106 insertions, 34 deletions
diff --git a/fs/inode.c b/fs/inode.c index 5aab80dc008c..73920d555c88 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -143,6 +143,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode) | |||
| 143 | inode->i_op = &empty_iops; | 143 | inode->i_op = &empty_iops; |
| 144 | inode->i_fop = &empty_fops; | 144 | inode->i_fop = &empty_fops; |
| 145 | inode->i_nlink = 1; | 145 | inode->i_nlink = 1; |
| 146 | inode->i_opflags = 0; | ||
| 146 | inode->i_uid = 0; | 147 | inode->i_uid = 0; |
| 147 | inode->i_gid = 0; | 148 | inode->i_gid = 0; |
| 148 | atomic_set(&inode->i_writecount, 0); | 149 | atomic_set(&inode->i_writecount, 0); |
diff --git a/fs/namei.c b/fs/namei.c index 3d607bd80e09..4a98bf154d88 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -308,6 +308,26 @@ int generic_permission(struct inode *inode, int mask) | |||
| 308 | return -EACCES; | 308 | return -EACCES; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | /* | ||
| 312 | * We _really_ want to just do "generic_permission()" without | ||
| 313 | * even looking at the inode->i_op values. So we keep a cache | ||
| 314 | * flag in inode->i_opflags, that says "this has not special | ||
| 315 | * permission function, use the fast case". | ||
| 316 | */ | ||
| 317 | static inline int do_inode_permission(struct inode *inode, int mask) | ||
| 318 | { | ||
| 319 | if (unlikely(!(inode->i_opflags & IOP_FASTPERM))) { | ||
| 320 | if (likely(inode->i_op->permission)) | ||
| 321 | return inode->i_op->permission(inode, mask); | ||
| 322 | |||
| 323 | /* This gets set once for the inode lifetime */ | ||
| 324 | spin_lock(&inode->i_lock); | ||
| 325 | inode->i_opflags |= IOP_FASTPERM; | ||
| 326 | spin_unlock(&inode->i_lock); | ||
| 327 | } | ||
| 328 | return generic_permission(inode, mask); | ||
| 329 | } | ||
| 330 | |||
| 311 | /** | 331 | /** |
| 312 | * inode_permission - check for access rights to a given inode | 332 | * inode_permission - check for access rights to a given inode |
| 313 | * @inode: inode to check permission on | 333 | * @inode: inode to check permission on |
| @@ -322,7 +342,7 @@ int inode_permission(struct inode *inode, int mask) | |||
| 322 | { | 342 | { |
| 323 | int retval; | 343 | int retval; |
| 324 | 344 | ||
| 325 | if (mask & MAY_WRITE) { | 345 | if (unlikely(mask & MAY_WRITE)) { |
| 326 | umode_t mode = inode->i_mode; | 346 | umode_t mode = inode->i_mode; |
| 327 | 347 | ||
| 328 | /* | 348 | /* |
| @@ -339,11 +359,7 @@ int inode_permission(struct inode *inode, int mask) | |||
| 339 | return -EACCES; | 359 | return -EACCES; |
| 340 | } | 360 | } |
| 341 | 361 | ||
| 342 | if (inode->i_op->permission) | 362 | retval = do_inode_permission(inode, mask); |
| 343 | retval = inode->i_op->permission(inode, mask); | ||
| 344 | else | ||
| 345 | retval = generic_permission(inode, mask); | ||
| 346 | |||
| 347 | if (retval) | 363 | if (retval) |
| 348 | return retval; | 364 | return retval; |
| 349 | 365 | ||
| @@ -1245,6 +1261,26 @@ static void terminate_walk(struct nameidata *nd) | |||
| 1245 | } | 1261 | } |
| 1246 | } | 1262 | } |
| 1247 | 1263 | ||
| 1264 | /* | ||
| 1265 | * Do we need to follow links? We _really_ want to be able | ||
| 1266 | * to do this check without having to look at inode->i_op, | ||
| 1267 | * so we keep a cache of "no, this doesn't need follow_link" | ||
| 1268 | * for the common case. | ||
| 1269 | */ | ||
| 1270 | static inline int do_follow_link(struct inode *inode, int follow) | ||
| 1271 | { | ||
| 1272 | if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) { | ||
| 1273 | if (likely(inode->i_op->follow_link)) | ||
| 1274 | return follow; | ||
| 1275 | |||
| 1276 | /* This gets set once for the inode lifetime */ | ||
| 1277 | spin_lock(&inode->i_lock); | ||
| 1278 | inode->i_opflags |= IOP_NOFOLLOW; | ||
| 1279 | spin_unlock(&inode->i_lock); | ||
| 1280 | } | ||
| 1281 | return 0; | ||
| 1282 | } | ||
| 1283 | |||
| 1248 | static inline int walk_component(struct nameidata *nd, struct path *path, | 1284 | static inline int walk_component(struct nameidata *nd, struct path *path, |
| 1249 | struct qstr *name, int type, int follow) | 1285 | struct qstr *name, int type, int follow) |
| 1250 | { | 1286 | { |
| @@ -1267,7 +1303,7 @@ static inline int walk_component(struct nameidata *nd, struct path *path, | |||
| 1267 | terminate_walk(nd); | 1303 | terminate_walk(nd); |
| 1268 | return -ENOENT; | 1304 | return -ENOENT; |
| 1269 | } | 1305 | } |
| 1270 | if (unlikely(inode->i_op->follow_link) && follow) { | 1306 | if (do_follow_link(inode, follow)) { |
| 1271 | if (nd->flags & LOOKUP_RCU) { | 1307 | if (nd->flags & LOOKUP_RCU) { |
| 1272 | if (unlikely(unlazy_walk(nd, path->dentry))) { | 1308 | if (unlikely(unlazy_walk(nd, path->dentry))) { |
| 1273 | terminate_walk(nd); | 1309 | terminate_walk(nd); |
| @@ -1320,6 +1356,26 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd) | |||
| 1320 | } | 1356 | } |
| 1321 | 1357 | ||
| 1322 | /* | 1358 | /* |
| 1359 | * We really don't want to look at inode->i_op->lookup | ||
| 1360 | * when we don't have to. So we keep a cache bit in | ||
| 1361 | * the inode ->i_opflags field that says "yes, we can | ||
| 1362 | * do lookup on this inode". | ||
| 1363 | */ | ||
| 1364 | static inline int can_lookup(struct inode *inode) | ||
| 1365 | { | ||
| 1366 | if (likely(inode->i_opflags & IOP_LOOKUP)) | ||
| 1367 | return 1; | ||
| 1368 | if (likely(!inode->i_op->lookup)) | ||
| 1369 | return 0; | ||
| 1370 | |||
| 1371 | /* We do this once for the lifetime of the inode */ | ||
| 1372 | spin_lock(&inode->i_lock); | ||
| 1373 | inode->i_opflags |= IOP_LOOKUP; | ||
| 1374 | spin_unlock(&inode->i_lock); | ||
| 1375 | return 1; | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | /* | ||
| 1323 | * Name resolution. | 1379 | * Name resolution. |
| 1324 | * This is the basic name resolution function, turning a pathname into | 1380 | * This is the basic name resolution function, turning a pathname into |
| 1325 | * the final dentry. We expect 'base' to be positive and a directory. | 1381 | * the final dentry. We expect 'base' to be positive and a directory. |
| @@ -1398,10 +1454,10 @@ static int link_path_walk(const char *name, struct nameidata *nd) | |||
| 1398 | if (err) | 1454 | if (err) |
| 1399 | return err; | 1455 | return err; |
| 1400 | } | 1456 | } |
| 1457 | if (can_lookup(nd->inode)) | ||
| 1458 | continue; | ||
| 1401 | err = -ENOTDIR; | 1459 | err = -ENOTDIR; |
| 1402 | if (!nd->inode->i_op->lookup) | 1460 | break; |
| 1403 | break; | ||
| 1404 | continue; | ||
| 1405 | /* here ends the main loop */ | 1461 | /* here ends the main loop */ |
| 1406 | 1462 | ||
| 1407 | last_component: | 1463 | last_component: |
| @@ -27,12 +27,12 @@ void generic_fillattr(struct inode *inode, struct kstat *stat) | |||
| 27 | stat->uid = inode->i_uid; | 27 | stat->uid = inode->i_uid; |
| 28 | stat->gid = inode->i_gid; | 28 | stat->gid = inode->i_gid; |
| 29 | stat->rdev = inode->i_rdev; | 29 | stat->rdev = inode->i_rdev; |
| 30 | stat->size = i_size_read(inode); | ||
| 30 | stat->atime = inode->i_atime; | 31 | stat->atime = inode->i_atime; |
| 31 | stat->mtime = inode->i_mtime; | 32 | stat->mtime = inode->i_mtime; |
| 32 | stat->ctime = inode->i_ctime; | 33 | stat->ctime = inode->i_ctime; |
| 33 | stat->size = i_size_read(inode); | ||
| 34 | stat->blocks = inode->i_blocks; | ||
| 35 | stat->blksize = (1 << inode->i_blkbits); | 34 | stat->blksize = (1 << inode->i_blkbits); |
| 35 | stat->blocks = inode->i_blocks; | ||
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | EXPORT_SYMBOL(generic_fillattr); | 38 | EXPORT_SYMBOL(generic_fillattr); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 786b3b1113cf..178cdb4f1d4a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -738,22 +738,54 @@ static inline int mapping_writably_mapped(struct address_space *mapping) | |||
| 738 | struct posix_acl; | 738 | struct posix_acl; |
| 739 | #define ACL_NOT_CACHED ((void *)(-1)) | 739 | #define ACL_NOT_CACHED ((void *)(-1)) |
| 740 | 740 | ||
| 741 | #define IOP_FASTPERM 0x0001 | ||
| 742 | #define IOP_LOOKUP 0x0002 | ||
| 743 | #define IOP_NOFOLLOW 0x0004 | ||
| 744 | |||
| 745 | /* | ||
| 746 | * Keep mostly read-only and often accessed (especially for | ||
| 747 | * the RCU path lookup and 'stat' data) fields at the beginning | ||
| 748 | * of the 'struct inode' | ||
| 749 | */ | ||
| 741 | struct inode { | 750 | struct inode { |
| 742 | /* RCU path lookup touches following: */ | ||
| 743 | umode_t i_mode; | 751 | umode_t i_mode; |
| 752 | unsigned short i_opflags; | ||
| 744 | uid_t i_uid; | 753 | uid_t i_uid; |
| 745 | gid_t i_gid; | 754 | gid_t i_gid; |
| 755 | unsigned int i_flags; | ||
| 756 | |||
| 757 | #ifdef CONFIG_FS_POSIX_ACL | ||
| 758 | struct posix_acl *i_acl; | ||
| 759 | struct posix_acl *i_default_acl; | ||
| 760 | #endif | ||
| 761 | |||
| 746 | const struct inode_operations *i_op; | 762 | const struct inode_operations *i_op; |
| 747 | struct super_block *i_sb; | 763 | struct super_block *i_sb; |
| 764 | struct address_space *i_mapping; | ||
| 748 | 765 | ||
| 749 | spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ | ||
| 750 | unsigned int i_flags; | ||
| 751 | unsigned long i_state; | ||
| 752 | #ifdef CONFIG_SECURITY | 766 | #ifdef CONFIG_SECURITY |
| 753 | void *i_security; | 767 | void *i_security; |
| 754 | #endif | 768 | #endif |
| 755 | struct mutex i_mutex; | ||
| 756 | 769 | ||
| 770 | /* Stat data, not accessed from path walking */ | ||
| 771 | unsigned long i_ino; | ||
| 772 | unsigned int i_nlink; | ||
| 773 | dev_t i_rdev; | ||
| 774 | loff_t i_size; | ||
| 775 | struct timespec i_atime; | ||
| 776 | struct timespec i_mtime; | ||
| 777 | struct timespec i_ctime; | ||
| 778 | unsigned int i_blkbits; | ||
| 779 | blkcnt_t i_blocks; | ||
| 780 | |||
| 781 | #ifdef __NEED_I_SIZE_ORDERED | ||
| 782 | seqcount_t i_size_seqcount; | ||
| 783 | #endif | ||
| 784 | |||
| 785 | /* Misc */ | ||
| 786 | unsigned long i_state; | ||
| 787 | spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ | ||
| 788 | struct mutex i_mutex; | ||
| 757 | 789 | ||
| 758 | unsigned long dirtied_when; /* jiffies of first dirtying */ | 790 | unsigned long dirtied_when; /* jiffies of first dirtying */ |
| 759 | 791 | ||
| @@ -765,25 +797,12 @@ struct inode { | |||
| 765 | struct list_head i_dentry; | 797 | struct list_head i_dentry; |
| 766 | struct rcu_head i_rcu; | 798 | struct rcu_head i_rcu; |
| 767 | }; | 799 | }; |
| 768 | unsigned long i_ino; | ||
| 769 | atomic_t i_count; | 800 | atomic_t i_count; |
| 770 | unsigned int i_nlink; | ||
| 771 | dev_t i_rdev; | ||
| 772 | unsigned int i_blkbits; | ||
| 773 | u64 i_version; | 801 | u64 i_version; |
| 774 | loff_t i_size; | ||
| 775 | #ifdef __NEED_I_SIZE_ORDERED | ||
| 776 | seqcount_t i_size_seqcount; | ||
| 777 | #endif | ||
| 778 | struct timespec i_atime; | ||
| 779 | struct timespec i_mtime; | ||
| 780 | struct timespec i_ctime; | ||
| 781 | blkcnt_t i_blocks; | ||
| 782 | unsigned short i_bytes; | 802 | unsigned short i_bytes; |
| 783 | atomic_t i_dio_count; | 803 | atomic_t i_dio_count; |
| 784 | const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ | 804 | const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ |
| 785 | struct file_lock *i_flock; | 805 | struct file_lock *i_flock; |
| 786 | struct address_space *i_mapping; | ||
| 787 | struct address_space i_data; | 806 | struct address_space i_data; |
| 788 | #ifdef CONFIG_QUOTA | 807 | #ifdef CONFIG_QUOTA |
| 789 | struct dquot *i_dquot[MAXQUOTAS]; | 808 | struct dquot *i_dquot[MAXQUOTAS]; |
| @@ -806,10 +825,6 @@ struct inode { | |||
| 806 | atomic_t i_readcount; /* struct files open RO */ | 825 | atomic_t i_readcount; /* struct files open RO */ |
| 807 | #endif | 826 | #endif |
| 808 | atomic_t i_writecount; | 827 | atomic_t i_writecount; |
| 809 | #ifdef CONFIG_FS_POSIX_ACL | ||
| 810 | struct posix_acl *i_acl; | ||
| 811 | struct posix_acl *i_default_acl; | ||
| 812 | #endif | ||
| 813 | void *i_private; /* fs or device private pointer */ | 828 | void *i_private; /* fs or device private pointer */ |
| 814 | }; | 829 | }; |
| 815 | 830 | ||
