aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c88
1 files changed, 66 insertions, 22 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index b94c0da3b43f..4d14de6d121b 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4009,12 +4009,19 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
4009 struct btrfs_root *sub_root = root; 4009 struct btrfs_root *sub_root = root;
4010 struct btrfs_key location; 4010 struct btrfs_key location;
4011 int index; 4011 int index;
4012 int ret; 4012 int ret = 0;
4013 4013
4014 if (dentry->d_name.len > BTRFS_NAME_LEN) 4014 if (dentry->d_name.len > BTRFS_NAME_LEN)
4015 return ERR_PTR(-ENAMETOOLONG); 4015 return ERR_PTR(-ENAMETOOLONG);
4016 4016
4017 ret = btrfs_inode_by_name(dir, dentry, &location); 4017 if (unlikely(d_need_lookup(dentry))) {
4018 memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key));
4019 kfree(dentry->d_fsdata);
4020 dentry->d_fsdata = NULL;
4021 d_clear_need_lookup(dentry);
4022 } else {
4023 ret = btrfs_inode_by_name(dir, dentry, &location);
4024 }
4018 4025
4019 if (ret < 0) 4026 if (ret < 0)
4020 return ERR_PTR(ret); 4027 return ERR_PTR(ret);
@@ -4069,16 +4076,16 @@ static int btrfs_dentry_delete(const struct dentry *dentry)
4069 return 0; 4076 return 0;
4070} 4077}
4071 4078
4079static void btrfs_dentry_release(struct dentry *dentry)
4080{
4081 if (dentry->d_fsdata)
4082 kfree(dentry->d_fsdata);
4083}
4084
4072static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, 4085static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
4073 struct nameidata *nd) 4086 struct nameidata *nd)
4074{ 4087{
4075 struct inode *inode; 4088 return d_splice_alias(btrfs_lookup_dentry(dir, dentry), dentry);
4076
4077 inode = btrfs_lookup_dentry(dir, dentry);
4078 if (IS_ERR(inode))
4079 return ERR_CAST(inode);
4080
4081 return d_splice_alias(inode, dentry);
4082} 4089}
4083 4090
4084unsigned char btrfs_filetype_table[] = { 4091unsigned char btrfs_filetype_table[] = {
@@ -4097,6 +4104,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
4097 struct btrfs_path *path; 4104 struct btrfs_path *path;
4098 struct list_head ins_list; 4105 struct list_head ins_list;
4099 struct list_head del_list; 4106 struct list_head del_list;
4107 struct qstr q;
4100 int ret; 4108 int ret;
4101 struct extent_buffer *leaf; 4109 struct extent_buffer *leaf;
4102 int slot; 4110 int slot;
@@ -4186,6 +4194,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
4186 4194
4187 while (di_cur < di_total) { 4195 while (di_cur < di_total) {
4188 struct btrfs_key location; 4196 struct btrfs_key location;
4197 struct dentry *tmp;
4189 4198
4190 if (verify_dir_item(root, leaf, di)) 4199 if (verify_dir_item(root, leaf, di))
4191 break; 4200 break;
@@ -4206,6 +4215,33 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
4206 d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; 4215 d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
4207 btrfs_dir_item_key_to_cpu(leaf, di, &location); 4216 btrfs_dir_item_key_to_cpu(leaf, di, &location);
4208 4217
4218 q.name = name_ptr;
4219 q.len = name_len;
4220 q.hash = full_name_hash(q.name, q.len);
4221 tmp = d_lookup(filp->f_dentry, &q);
4222 if (!tmp) {
4223 struct btrfs_key *newkey;
4224
4225 newkey = kzalloc(sizeof(struct btrfs_key),
4226 GFP_NOFS);
4227 if (!newkey)
4228 goto no_dentry;
4229 tmp = d_alloc(filp->f_dentry, &q);
4230 if (!tmp) {
4231 kfree(newkey);
4232 dput(tmp);
4233 goto no_dentry;
4234 }
4235 memcpy(newkey, &location,
4236 sizeof(struct btrfs_key));
4237 tmp->d_fsdata = newkey;
4238 tmp->d_flags |= DCACHE_NEED_LOOKUP;
4239 d_rehash(tmp);
4240 dput(tmp);
4241 } else {
4242 dput(tmp);
4243 }
4244no_dentry:
4209 /* is this a reference to our own snapshot? If so 4245 /* is this a reference to our own snapshot? If so
4210 * skip it 4246 * skip it
4211 */ 4247 */
@@ -4467,7 +4503,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
4467 inode->i_generation = BTRFS_I(inode)->generation; 4503 inode->i_generation = BTRFS_I(inode)->generation;
4468 btrfs_set_inode_space_info(root, inode); 4504 btrfs_set_inode_space_info(root, inode);
4469 4505
4470 if (mode & S_IFDIR) 4506 if (S_ISDIR(mode))
4471 owner = 0; 4507 owner = 0;
4472 else 4508 else
4473 owner = 1; 4509 owner = 1;
@@ -4512,7 +4548,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
4512 4548
4513 btrfs_inherit_iflags(inode, dir); 4549 btrfs_inherit_iflags(inode, dir);
4514 4550
4515 if ((mode & S_IFREG)) { 4551 if (S_ISREG(mode)) {
4516 if (btrfs_test_opt(root, NODATASUM)) 4552 if (btrfs_test_opt(root, NODATASUM))
4517 BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM; 4553 BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
4518 if (btrfs_test_opt(root, NODATACOW) || 4554 if (btrfs_test_opt(root, NODATACOW) ||
@@ -4766,11 +4802,10 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
4766 if (err) { 4802 if (err) {
4767 drop_inode = 1; 4803 drop_inode = 1;
4768 } else { 4804 } else {
4769 struct dentry *parent = dget_parent(dentry); 4805 struct dentry *parent = dentry->d_parent;
4770 err = btrfs_update_inode(trans, root, inode); 4806 err = btrfs_update_inode(trans, root, inode);
4771 BUG_ON(err); 4807 BUG_ON(err);
4772 btrfs_log_new_name(trans, inode, NULL, parent); 4808 btrfs_log_new_name(trans, inode, NULL, parent);
4773 dput(parent);
4774 } 4809 }
4775 4810
4776 nr = trans->blocks_used; 4811 nr = trans->blocks_used;
@@ -6882,7 +6917,7 @@ static int btrfs_getattr(struct vfsmount *mnt,
6882{ 6917{
6883 struct inode *inode = dentry->d_inode; 6918 struct inode *inode = dentry->d_inode;
6884 generic_fillattr(inode, stat); 6919 generic_fillattr(inode, stat);
6885 stat->dev = BTRFS_I(inode)->root->anon_super.s_dev; 6920 stat->dev = BTRFS_I(inode)->root->anon_dev;
6886 stat->blksize = PAGE_CACHE_SIZE; 6921 stat->blksize = PAGE_CACHE_SIZE;
6887 stat->blocks = (inode_get_bytes(inode) + 6922 stat->blocks = (inode_get_bytes(inode) +
6888 BTRFS_I(inode)->delalloc_bytes) >> 9; 6923 BTRFS_I(inode)->delalloc_bytes) >> 9;
@@ -7050,9 +7085,8 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
7050 BUG_ON(ret); 7085 BUG_ON(ret);
7051 7086
7052 if (old_ino != BTRFS_FIRST_FREE_OBJECTID) { 7087 if (old_ino != BTRFS_FIRST_FREE_OBJECTID) {
7053 struct dentry *parent = dget_parent(new_dentry); 7088 struct dentry *parent = new_dentry->d_parent;
7054 btrfs_log_new_name(trans, old_inode, old_dir, parent); 7089 btrfs_log_new_name(trans, old_inode, old_dir, parent);
7055 dput(parent);
7056 btrfs_end_log_trans(root); 7090 btrfs_end_log_trans(root);
7057 } 7091 }
7058out_fail: 7092out_fail:
@@ -7317,15 +7351,19 @@ static int btrfs_set_page_dirty(struct page *page)
7317 return __set_page_dirty_nobuffers(page); 7351 return __set_page_dirty_nobuffers(page);
7318} 7352}
7319 7353
7320static int btrfs_permission(struct inode *inode, int mask, unsigned int flags) 7354static int btrfs_permission(struct inode *inode, int mask)
7321{ 7355{
7322 struct btrfs_root *root = BTRFS_I(inode)->root; 7356 struct btrfs_root *root = BTRFS_I(inode)->root;
7357 umode_t mode = inode->i_mode;
7323 7358
7324 if (btrfs_root_readonly(root) && (mask & MAY_WRITE)) 7359 if (mask & MAY_WRITE &&
7325 return -EROFS; 7360 (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) {
7326 if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE)) 7361 if (btrfs_root_readonly(root))
7327 return -EACCES; 7362 return -EROFS;
7328 return generic_permission(inode, mask, flags, btrfs_check_acl); 7363 if (BTRFS_I(inode)->flags & BTRFS_INODE_READONLY)
7364 return -EACCES;
7365 }
7366 return generic_permission(inode, mask);
7329} 7367}
7330 7368
7331static const struct inode_operations btrfs_dir_inode_operations = { 7369static const struct inode_operations btrfs_dir_inode_operations = {
@@ -7345,10 +7383,12 @@ static const struct inode_operations btrfs_dir_inode_operations = {
7345 .listxattr = btrfs_listxattr, 7383 .listxattr = btrfs_listxattr,
7346 .removexattr = btrfs_removexattr, 7384 .removexattr = btrfs_removexattr,
7347 .permission = btrfs_permission, 7385 .permission = btrfs_permission,
7386 .get_acl = btrfs_get_acl,
7348}; 7387};
7349static const struct inode_operations btrfs_dir_ro_inode_operations = { 7388static const struct inode_operations btrfs_dir_ro_inode_operations = {
7350 .lookup = btrfs_lookup, 7389 .lookup = btrfs_lookup,
7351 .permission = btrfs_permission, 7390 .permission = btrfs_permission,
7391 .get_acl = btrfs_get_acl,
7352}; 7392};
7353 7393
7354static const struct file_operations btrfs_dir_file_operations = { 7394static const struct file_operations btrfs_dir_file_operations = {
@@ -7417,6 +7457,7 @@ static const struct inode_operations btrfs_file_inode_operations = {
7417 .removexattr = btrfs_removexattr, 7457 .removexattr = btrfs_removexattr,
7418 .permission = btrfs_permission, 7458 .permission = btrfs_permission,
7419 .fiemap = btrfs_fiemap, 7459 .fiemap = btrfs_fiemap,
7460 .get_acl = btrfs_get_acl,
7420}; 7461};
7421static const struct inode_operations btrfs_special_inode_operations = { 7462static const struct inode_operations btrfs_special_inode_operations = {
7422 .getattr = btrfs_getattr, 7463 .getattr = btrfs_getattr,
@@ -7426,6 +7467,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
7426 .getxattr = btrfs_getxattr, 7467 .getxattr = btrfs_getxattr,
7427 .listxattr = btrfs_listxattr, 7468 .listxattr = btrfs_listxattr,
7428 .removexattr = btrfs_removexattr, 7469 .removexattr = btrfs_removexattr,
7470 .get_acl = btrfs_get_acl,
7429}; 7471};
7430static const struct inode_operations btrfs_symlink_inode_operations = { 7472static const struct inode_operations btrfs_symlink_inode_operations = {
7431 .readlink = generic_readlink, 7473 .readlink = generic_readlink,
@@ -7437,8 +7479,10 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
7437 .getxattr = btrfs_getxattr, 7479 .getxattr = btrfs_getxattr,
7438 .listxattr = btrfs_listxattr, 7480 .listxattr = btrfs_listxattr,
7439 .removexattr = btrfs_removexattr, 7481 .removexattr = btrfs_removexattr,
7482 .get_acl = btrfs_get_acl,
7440}; 7483};
7441 7484
7442const struct dentry_operations btrfs_dentry_operations = { 7485const struct dentry_operations btrfs_dentry_operations = {
7443 .d_delete = btrfs_dentry_delete, 7486 .d_delete = btrfs_dentry_delete,
7487 .d_release = btrfs_dentry_release,
7444}; 7488};