Skip to content

Commit 69d803c

Browse files
Yang Erkunchucklever
authored andcommitted
nfsd: Revert "nfsd: release svc_expkey/svc_export with rcu_work"
This reverts commit f8c989a. Before this commit, svc_export_put or expkey_put will call path_put with sync mode. After this commit, path_put will be called with async mode. And this can lead the unexpected results show as follow. mkfs.xfs -f /dev/sda echo "/ *(rw,no_root_squash,fsid=0)" > /etc/exports echo "/mnt *(rw,no_root_squash,fsid=1)" >> /etc/exports exportfs -ra service nfs-server start mount -t nfs -o vers=4.0 127.0.0.1:/mnt /mnt1 mount /dev/sda /mnt/sda touch /mnt1/sda/file exportfs -r umount /mnt/sda # failed unexcepted The touch will finally call nfsd_cross_mnt, add refcount to mount, and then add cache_head. Before this commit, exportfs -r will call cache_flush to cleanup all cache_head, and path_put in svc_export_put/expkey_put will be finished with sync mode. So, the latter umount will always success. However, after this commit, path_put will be called with async mode, the latter umount may failed, and if we add some delay, umount will success too. Personally I think this bug and should be fixed. We first revert before bugfix patch, and then fix the original bug with a different way. Fixes: f8c989a ("nfsd: release svc_expkey/svc_export with rcu_work") Signed-off-by: Yang Erkun <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 583772e commit 69d803c

File tree

2 files changed

+8
-27
lines changed

2 files changed

+8
-27
lines changed

fs/nfsd/export.c

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,15 @@
4040
#define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
4141
#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
4242

43-
static void expkey_put_work(struct work_struct *work)
43+
static void expkey_put(struct kref *ref)
4444
{
45-
struct svc_expkey *key =
46-
container_of(to_rcu_work(work), struct svc_expkey, ek_rcu_work);
45+
struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
4746

4847
if (test_bit(CACHE_VALID, &key->h.flags) &&
4948
!test_bit(CACHE_NEGATIVE, &key->h.flags))
5049
path_put(&key->ek_path);
5150
auth_domain_put(key->ek_client);
52-
kfree(key);
53-
}
54-
55-
static void expkey_put(struct kref *ref)
56-
{
57-
struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
58-
59-
INIT_RCU_WORK(&key->ek_rcu_work, expkey_put_work);
60-
queue_rcu_work(system_wq, &key->ek_rcu_work);
51+
kfree_rcu(key, ek_rcu);
6152
}
6253

6354
static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
@@ -364,26 +355,16 @@ static void export_stats_destroy(struct export_stats *stats)
364355
EXP_STATS_COUNTERS_NUM);
365356
}
366357

367-
static void svc_export_put_work(struct work_struct *work)
358+
static void svc_export_put(struct kref *ref)
368359
{
369-
struct svc_export *exp =
370-
container_of(to_rcu_work(work), struct svc_export, ex_rcu_work);
371-
360+
struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
372361
path_put(&exp->ex_path);
373362
auth_domain_put(exp->ex_client);
374363
nfsd4_fslocs_free(&exp->ex_fslocs);
375364
export_stats_destroy(exp->ex_stats);
376365
kfree(exp->ex_stats);
377366
kfree(exp->ex_uuid);
378-
kfree(exp);
379-
}
380-
381-
static void svc_export_put(struct kref *ref)
382-
{
383-
struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
384-
385-
INIT_RCU_WORK(&exp->ex_rcu_work, svc_export_put_work);
386-
queue_rcu_work(system_wq, &exp->ex_rcu_work);
367+
kfree_rcu(exp, ex_rcu);
387368
}
388369

389370
static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)

fs/nfsd/export.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ struct svc_export {
7575
u32 ex_layout_types;
7676
struct nfsd4_deviceid_map *ex_devid_map;
7777
struct cache_detail *cd;
78-
struct rcu_work ex_rcu_work;
78+
struct rcu_head ex_rcu;
7979
unsigned long ex_xprtsec_modes;
8080
struct export_stats *ex_stats;
8181
};
@@ -92,7 +92,7 @@ struct svc_expkey {
9292
u32 ek_fsid[6];
9393

9494
struct path ek_path;
95-
struct rcu_work ek_rcu_work;
95+
struct rcu_head ek_rcu;
9696
};
9797

9898
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))

0 commit comments

Comments
 (0)