diff options
| author | Jeff Layton <jlayton@redhat.com> | 2010-10-06 19:51:12 -0400 |
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2010-10-07 23:31:21 -0400 |
| commit | 2de970ff69bbcc5a4b7440df669a595b2b1acd73 (patch) | |
| tree | ec710893fcd1aa6313a3bbe2eafb3f463b364afc | |
| parent | 3aa1c8c2900065a51268430ab48a1b42fdfe5b45 (diff) | |
cifs: implement recurring workqueue job to prune old tcons
Create a workqueue job that cleans out unused tlinks. For now, it uses
a hardcoded expire time of 10 minutes. When it's done, the work rearms
itself. On umount, the work is cancelled before tearing down the tlink
tree.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
| -rw-r--r-- | fs/cifs/cifs_fs_sb.h | 1 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 58 |
2 files changed, 58 insertions, 1 deletions
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 5ce57bdf1865..586ee3d527d2 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
| @@ -59,5 +59,6 @@ struct cifs_sb_info { | |||
| 59 | char *mountdata; /* mount options received at mount time */ | 59 | char *mountdata; /* mount options received at mount time */ |
| 60 | #endif | 60 | #endif |
| 61 | struct backing_dev_info bdi; | 61 | struct backing_dev_info bdi; |
| 62 | struct delayed_work prune_tlinks; | ||
| 62 | }; | 63 | }; |
| 63 | #endif /* _CIFS_FS_SB_H */ | 64 | #endif /* _CIFS_FS_SB_H */ |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e65f72d1f23b..1092e9e839c2 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -110,11 +110,13 @@ struct smb_vol { | |||
| 110 | struct nls_table *local_nls; | 110 | struct nls_table *local_nls; |
| 111 | }; | 111 | }; |
| 112 | 112 | ||
| 113 | /* FIXME: should these be tunable? */ | ||
| 113 | #define TLINK_ERROR_EXPIRE (1 * HZ) | 114 | #define TLINK_ERROR_EXPIRE (1 * HZ) |
| 114 | 115 | #define TLINK_IDLE_EXPIRE (600 * HZ) | |
| 115 | 116 | ||
| 116 | static int ipv4_connect(struct TCP_Server_Info *server); | 117 | static int ipv4_connect(struct TCP_Server_Info *server); |
| 117 | static int ipv6_connect(struct TCP_Server_Info *server); | 118 | static int ipv6_connect(struct TCP_Server_Info *server); |
| 119 | static void cifs_prune_tlinks(struct work_struct *work); | ||
| 118 | 120 | ||
| 119 | /* | 121 | /* |
| 120 | * cifs tcp session reconnection | 122 | * cifs tcp session reconnection |
| @@ -2494,6 +2496,8 @@ convert_delimiter(char *path, char delim) | |||
| 2494 | static void setup_cifs_sb(struct smb_vol *pvolume_info, | 2496 | static void setup_cifs_sb(struct smb_vol *pvolume_info, |
| 2495 | struct cifs_sb_info *cifs_sb) | 2497 | struct cifs_sb_info *cifs_sb) |
| 2496 | { | 2498 | { |
| 2499 | INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); | ||
| 2500 | |||
| 2497 | if (pvolume_info->rsize > CIFSMaxBufSize) { | 2501 | if (pvolume_info->rsize > CIFSMaxBufSize) { |
| 2498 | cERROR(1, "rsize %d too large, using MaxBufSize", | 2502 | cERROR(1, "rsize %d too large, using MaxBufSize", |
| 2499 | pvolume_info->rsize); | 2503 | pvolume_info->rsize); |
| @@ -2899,6 +2903,9 @@ remote_path_check: | |||
| 2899 | spin_unlock(&cifs_sb->tlink_tree_lock); | 2903 | spin_unlock(&cifs_sb->tlink_tree_lock); |
| 2900 | radix_tree_preload_end(); | 2904 | radix_tree_preload_end(); |
| 2901 | 2905 | ||
| 2906 | queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks, | ||
| 2907 | TLINK_IDLE_EXPIRE); | ||
| 2908 | |||
| 2902 | mount_fail_check: | 2909 | mount_fail_check: |
| 2903 | /* on error free sesinfo and tcon struct if needed */ | 2910 | /* on error free sesinfo and tcon struct if needed */ |
| 2904 | if (rc) { | 2911 | if (rc) { |
| @@ -3090,6 +3097,8 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
| 3090 | struct tcon_link *tlink[8]; | 3097 | struct tcon_link *tlink[8]; |
| 3091 | unsigned long index = 0; | 3098 | unsigned long index = 0; |
| 3092 | 3099 | ||
| 3100 | cancel_delayed_work_sync(&cifs_sb->prune_tlinks); | ||
| 3101 | |||
| 3093 | do { | 3102 | do { |
| 3094 | spin_lock(&cifs_sb->tlink_tree_lock); | 3103 | spin_lock(&cifs_sb->tlink_tree_lock); |
| 3095 | ret = radix_tree_gang_lookup(&cifs_sb->tlink_tree, | 3104 | ret = radix_tree_gang_lookup(&cifs_sb->tlink_tree, |
| @@ -3363,3 +3372,50 @@ wait_for_construction: | |||
| 3363 | 3372 | ||
| 3364 | return tlink; | 3373 | return tlink; |
| 3365 | } | 3374 | } |
| 3375 | |||
| 3376 | /* | ||
| 3377 | * periodic workqueue job that scans tcon_tree for a superblock and closes | ||
| 3378 | * out tcons. | ||
| 3379 | */ | ||
| 3380 | static void | ||
| 3381 | cifs_prune_tlinks(struct work_struct *work) | ||
| 3382 | { | ||
| 3383 | struct cifs_sb_info *cifs_sb = container_of(work, struct cifs_sb_info, | ||
| 3384 | prune_tlinks.work); | ||
| 3385 | struct tcon_link *tlink[8]; | ||
| 3386 | unsigned long now = jiffies; | ||
| 3387 | unsigned long index = 0; | ||
| 3388 | int i, ret; | ||
| 3389 | |||
| 3390 | do { | ||
| 3391 | spin_lock(&cifs_sb->tlink_tree_lock); | ||
| 3392 | ret = radix_tree_gang_lookup(&cifs_sb->tlink_tree, | ||
| 3393 | (void **)tlink, index, | ||
| 3394 | ARRAY_SIZE(tlink)); | ||
| 3395 | /* increment index for next pass */ | ||
| 3396 | if (ret > 0) | ||
| 3397 | index = tlink[ret - 1]->tl_index + 1; | ||
| 3398 | for (i = 0; i < ret; i++) { | ||
| 3399 | if (test_bit(TCON_LINK_MASTER, &tlink[i]->tl_flags) || | ||
| 3400 | atomic_read(&tlink[i]->tl_count) != 0 || | ||
| 3401 | time_after(tlink[i]->tl_time + TLINK_IDLE_EXPIRE, | ||
| 3402 | now)) { | ||
| 3403 | tlink[i] = NULL; | ||
| 3404 | continue; | ||
| 3405 | } | ||
| 3406 | cifs_get_tlink(tlink[i]); | ||
| 3407 | clear_bit(TCON_LINK_IN_TREE, &tlink[i]->tl_flags); | ||
| 3408 | radix_tree_delete(&cifs_sb->tlink_tree, | ||
| 3409 | tlink[i]->tl_index); | ||
| 3410 | } | ||
| 3411 | spin_unlock(&cifs_sb->tlink_tree_lock); | ||
| 3412 | |||
| 3413 | for (i = 0; i < ret; i++) { | ||
| 3414 | if (tlink[i] != NULL) | ||
| 3415 | cifs_put_tlink(tlink[i]); | ||
| 3416 | } | ||
| 3417 | } while (ret != 0); | ||
| 3418 | |||
| 3419 | queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks, | ||
| 3420 | TLINK_IDLE_EXPIRE); | ||
| 3421 | } | ||
