@@ -24,45 +24,46 @@ static const struct inode_operations kernfs_iops = {
24
24
.listxattr = kernfs_iop_listxattr ,
25
25
};
26
26
27
- static struct kernfs_iattrs * __kernfs_iattrs (struct kernfs_node * kn , int alloc )
27
+ static struct kernfs_iattrs * __kernfs_iattrs (struct kernfs_node * kn , bool alloc )
28
28
{
29
- static DEFINE_MUTEX ( iattr_mutex ) ;
30
- struct kernfs_iattrs * ret ;
29
+ struct kernfs_iattrs * ret __free ( kfree ) = NULL ;
30
+ struct kernfs_iattrs * attr ;
31
31
32
- mutex_lock (& iattr_mutex );
32
+ attr = READ_ONCE (kn -> iattr );
33
+ if (attr || !alloc )
34
+ return attr ;
33
35
34
- if (kn -> iattr || !alloc )
35
- goto out_unlock ;
36
-
37
- kn -> iattr = kmem_cache_zalloc (kernfs_iattrs_cache , GFP_KERNEL );
38
- if (!kn -> iattr )
39
- goto out_unlock ;
36
+ ret = kmem_cache_zalloc (kernfs_iattrs_cache , GFP_KERNEL );
37
+ if (!ret )
38
+ return NULL ;
40
39
41
40
/* assign default attributes */
42
- kn -> iattr -> ia_uid = GLOBAL_ROOT_UID ;
43
- kn -> iattr -> ia_gid = GLOBAL_ROOT_GID ;
44
-
45
- ktime_get_real_ts64 (& kn -> iattr -> ia_atime );
46
- kn -> iattr -> ia_mtime = kn -> iattr -> ia_atime ;
47
- kn -> iattr -> ia_ctime = kn -> iattr -> ia_atime ;
48
-
49
- simple_xattrs_init (& kn -> iattr -> xattrs );
50
- atomic_set (& kn -> iattr -> nr_user_xattrs , 0 );
51
- atomic_set (& kn -> iattr -> user_xattr_size , 0 );
52
- out_unlock :
53
- ret = kn -> iattr ;
54
- mutex_unlock (& iattr_mutex );
55
- return ret ;
41
+ ret -> ia_uid = GLOBAL_ROOT_UID ;
42
+ ret -> ia_gid = GLOBAL_ROOT_GID ;
43
+
44
+ ktime_get_real_ts64 (& ret -> ia_atime );
45
+ ret -> ia_mtime = ret -> ia_atime ;
46
+ ret -> ia_ctime = ret -> ia_atime ;
47
+
48
+ simple_xattrs_init (& ret -> xattrs );
49
+ atomic_set (& ret -> nr_user_xattrs , 0 );
50
+ atomic_set (& ret -> user_xattr_size , 0 );
51
+
52
+ /* If someone raced us, recognize it. */
53
+ if (!try_cmpxchg (& kn -> iattr , & attr , ret ))
54
+ return READ_ONCE (kn -> iattr );
55
+
56
+ return no_free_ptr (ret );
56
57
}
57
58
58
59
static struct kernfs_iattrs * kernfs_iattrs (struct kernfs_node * kn )
59
60
{
60
- return __kernfs_iattrs (kn , 1 );
61
+ return __kernfs_iattrs (kn , true );
61
62
}
62
63
63
64
static struct kernfs_iattrs * kernfs_iattrs_noalloc (struct kernfs_node * kn )
64
65
{
65
- return __kernfs_iattrs (kn , 0 );
66
+ return __kernfs_iattrs (kn , false );
66
67
}
67
68
68
69
int __kernfs_setattr (struct kernfs_node * kn , const struct iattr * iattr )
@@ -141,9 +142,9 @@ ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
141
142
struct kernfs_node * kn = kernfs_dentry_node (dentry );
142
143
struct kernfs_iattrs * attrs ;
143
144
144
- attrs = kernfs_iattrs (kn );
145
+ attrs = kernfs_iattrs_noalloc (kn );
145
146
if (!attrs )
146
- return - ENOMEM ;
147
+ return - ENODATA ;
147
148
148
149
return simple_xattr_list (d_inode (dentry ), & attrs -> xattrs , buf , size );
149
150
}
@@ -166,9 +167,10 @@ static inline void set_inode_attr(struct inode *inode,
166
167
167
168
static void kernfs_refresh_inode (struct kernfs_node * kn , struct inode * inode )
168
169
{
169
- struct kernfs_iattrs * attrs = kn -> iattr ;
170
+ struct kernfs_iattrs * attrs ;
170
171
171
172
inode -> i_mode = kn -> mode ;
173
+ attrs = kernfs_iattrs_noalloc (kn );
172
174
if (attrs )
173
175
/*
174
176
* kernfs_node has non-default attributes get them from
@@ -306,7 +308,9 @@ int kernfs_xattr_set(struct kernfs_node *kn, const char *name,
306
308
const void * value , size_t size , int flags )
307
309
{
308
310
struct simple_xattr * old_xattr ;
309
- struct kernfs_iattrs * attrs = kernfs_iattrs (kn );
311
+ struct kernfs_iattrs * attrs ;
312
+
313
+ attrs = kernfs_iattrs (kn );
310
314
if (!attrs )
311
315
return - ENOMEM ;
312
316
@@ -345,8 +349,9 @@ static int kernfs_vfs_user_xattr_add(struct kernfs_node *kn,
345
349
struct simple_xattrs * xattrs ,
346
350
const void * value , size_t size , int flags )
347
351
{
348
- atomic_t * sz = & kn -> iattr -> user_xattr_size ;
349
- atomic_t * nr = & kn -> iattr -> nr_user_xattrs ;
352
+ struct kernfs_iattrs * attr = kernfs_iattrs_noalloc (kn );
353
+ atomic_t * sz = & attr -> user_xattr_size ;
354
+ atomic_t * nr = & attr -> nr_user_xattrs ;
350
355
struct simple_xattr * old_xattr ;
351
356
int ret ;
352
357
@@ -384,8 +389,9 @@ static int kernfs_vfs_user_xattr_rm(struct kernfs_node *kn,
384
389
struct simple_xattrs * xattrs ,
385
390
const void * value , size_t size , int flags )
386
391
{
387
- atomic_t * sz = & kn -> iattr -> user_xattr_size ;
388
- atomic_t * nr = & kn -> iattr -> nr_user_xattrs ;
392
+ struct kernfs_iattrs * attr = kernfs_iattrs_noalloc (kn );
393
+ atomic_t * sz = & attr -> user_xattr_size ;
394
+ atomic_t * nr = & attr -> nr_user_xattrs ;
389
395
struct simple_xattr * old_xattr ;
390
396
391
397
old_xattr = simple_xattr_set (xattrs , full_name , value , size , flags );
0 commit comments