Skip to content

Commit 4d5b303

Browse files
glepnirchrisbra
authored andcommitted
patch 9.1.2024: 'fsync' option cannot be set per buffer
Problem: 'fsync' option cannot be set per buffer Solution: Make 'fsync' option global-local (glepnir) closes: #19019 Signed-off-by: glepnir <glephunter@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
1 parent 9266a2a commit 4d5b303

11 files changed

Lines changed: 63 additions & 13 deletions

File tree

runtime/doc/options.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*options.txt* For Vim version 9.1. Last change: 2025 Dec 23
1+
*options.txt* For Vim version 9.1. Last change: 2025 Dec 27
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -4274,7 +4274,7 @@ A jump table for the options with a short description can be found at |Q_op|.
42744274

42754275
*'fsync'* *'fs'* *'nofsync'* *'nofs'*
42764276
'fsync' 'fs' boolean (default on)
4277-
global
4277+
global or local to buffer |global-local|
42784278
When on, the library function fsync() will be called after writing a
42794279
file. This will flush a file to disk, ensuring that it is safely
42804280
written even on filesystems which do metadata-only journaling. This
@@ -4283,6 +4283,8 @@ A jump table for the options with a short description can be found at |Q_op|.
42834283
turning this off increases the chances of data loss after a crash. On
42844284
systems without an fsync() implementation, this variable is always
42854285
off.
4286+
This is a |global-local| option, so it can be set per buffer, for
4287+
example when writing to a slow filesystem.
42864288
Also see 'swapsync' for controlling fsync() on swap files.
42874289
'fsync' also applies to |writefile()| (unless a flag is used to
42884290
overrule it) and when writing undo files (see |undo-persistence|).

runtime/doc/version9.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
*version9.txt* For Vim version 9.1. Last change: 2025 Dec 21
1+
*version9.txt* For Vim version 9.1. Last change: 2025 Dec 27
22

33

44
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -41727,6 +41727,7 @@ Options: ~
4172741727
- 'guioptions': New value |'go-s'| to support fullscreen on MS-Windows GUI
4172841728
(see also the below platform specific change).
4172941729
- 'completepopup': Add more values to style popup windows.
41730+
- 'fsync' is now a |global-local| option.
4173041731

4173141732
Ex commands: ~
4173241733
- allow to specify a priority when defining a new sign |:sign-define|

src/buffer.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,6 +2538,9 @@ free_buf_options(
25382538
clear_string_option(&buf->b_p_qe);
25392539
buf->b_p_ac = -1;
25402540
buf->b_p_ar = -1;
2541+
#ifdef HAVE_FSYNC
2542+
buf->b_p_fs = -1;
2543+
#endif
25412544
buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
25422545
clear_string_option(&buf->b_p_lw);
25432546
clear_string_option(&buf->b_p_bkc);

src/bufwrite.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2199,7 +2199,8 @@ buf_write(
21992199
// For a device do try the fsync() but don't complain if it does not
22002200
// work (could be a pipe).
22012201
// If the 'fsync' option is FALSE, don't fsync(). Useful for laptops.
2202-
if (p_fs && vim_fsync(fd) != 0 && !device)
2202+
if ((buf->b_p_fs >= 0 ? buf->b_p_fs : p_fs) && vim_fsync(fd) != 0
2203+
&& !device)
22032204
{
22042205
errmsg = (char_u *)_(e_fsync_failed);
22052206
end = 0;

src/option.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,9 @@ set_init_1(int clean_arg)
698698
curbuf->b_p_initialized = TRUE;
699699
curbuf->b_p_ac = -1;
700700
curbuf->b_p_ar = -1; // no local 'autoread' value
701+
#ifdef HAVE_FSYNC
702+
curbuf->b_p_fs = -1; // no local 'fsync' value
703+
#endif
701704
curbuf->b_p_ul = NO_LOCAL_UNDOLEVEL;
702705
check_buf_options(curbuf);
703706
check_win_options(curwin);
@@ -2216,6 +2219,10 @@ do_set_option_bool(
22162219
value = -1;
22172220
else if ((int *)varp == &curbuf->b_p_ac && opt_flags == OPT_LOCAL)
22182221
value = -1;
2222+
#ifdef HAVE_FSYNC
2223+
else if ((int *)varp == &curbuf->b_p_fs && opt_flags == OPT_LOCAL)
2224+
value = -1;
2225+
#endif
22192226
else
22202227
value = *(int *)get_varp_scope(&(options[opt_idx]), OPT_GLOBAL);
22212228
}
@@ -6479,6 +6486,11 @@ unset_global_local_option(char_u *name, void *from)
64796486
case PV_AR:
64806487
buf->b_p_ar = -1;
64816488
break;
6489+
#ifdef HAVE_FSYNC
6490+
case PV_FS:
6491+
buf->b_p_fs = -1;
6492+
break;
6493+
#endif
64826494
case PV_BKC:
64836495
clear_string_option(&buf->b_p_bkc);
64846496
buf->b_bkc_flags = 0;
@@ -6613,6 +6625,9 @@ get_varp_scope(struct vimoption *p, int scope)
66136625
switch ((int)p->indir)
66146626
{
66156627
case PV_FP: return (char_u *)&(curbuf->b_p_fp);
6628+
#ifdef HAVE_FSYNC
6629+
case PV_FS: return (char_u *)&(curbuf->b_p_fs);
6630+
#endif
66166631
#ifdef FEAT_EVAL
66176632
case PV_FFU: return (char_u *)&(curbuf->b_p_ffu);
66186633
#endif
@@ -6737,6 +6752,10 @@ get_varp(struct vimoption *p)
67376752
#endif
67386753
case PV_FP: return *curbuf->b_p_fp != NUL
67396754
? (char_u *)&(curbuf->b_p_fp) : p->var;
6755+
#ifdef HAVE_FSYNC
6756+
case PV_FS: return curbuf->b_p_fs >= 0
6757+
? (char_u *)&(curbuf->b_p_fs) : p->var;
6758+
#endif
67406759
#ifdef FEAT_EVAL
67416760
case PV_FFU: return *curbuf->b_p_ffu != NUL
67426761
? (char_u *)&(curbuf->b_p_ffu) : p->var;
@@ -7540,6 +7559,9 @@ buf_copy_options(buf_T *buf, int flags)
75407559
// are not copied, start using the global value
75417560
buf->b_p_ac = -1;
75427561
buf->b_p_ar = -1;
7562+
#ifdef HAVE_FSYNC
7563+
buf->b_p_fs = -1;
7564+
#endif
75437565
buf->b_p_ul = NO_LOCAL_UNDOLEVEL;
75447566
buf->b_p_bkc = empty_option;
75457567
buf->b_bkc_flags = 0;

src/option.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,9 @@ enum
12231223
, BV_FF
12241224
, BV_FLP
12251225
, BV_FO
1226+
#ifdef HAVE_FSYNC
1227+
, BV_FS
1228+
#endif
12261229
, BV_FT
12271230
, BV_IMI
12281231
, BV_IMS

src/optiondefs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@
8282
#define PV_FF OPT_BUF(BV_FF)
8383
#define PV_FLP OPT_BUF(BV_FLP)
8484
#define PV_FO OPT_BUF(BV_FO)
85+
#ifdef HAVE_FSYNC
86+
# define PV_FS OPT_BOTH(OPT_BUF(BV_FS))
87+
#endif
8588
#define PV_FT OPT_BUF(BV_FT)
8689
#define PV_IMI OPT_BUF(BV_IMI)
8790
#define PV_IMS OPT_BUF(BV_IMS)
@@ -1172,7 +1175,7 @@ static struct vimoption options[] =
11721175
{(char_u *)"", (char_u *)0L} SCTX_INIT},
11731176
{"fsync", "fs", P_BOOL|P_SECURE|P_VI_DEF,
11741177
#ifdef HAVE_FSYNC
1175-
(char_u *)&p_fs, PV_NONE, NULL, NULL,
1178+
(char_u *)&p_fs, PV_FS, NULL, NULL,
11761179
{(char_u *)TRUE, (char_u *)0L}
11771180
#else
11781181
(char_u *)NULL, PV_NONE, NULL, NULL,

src/structs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3380,6 +3380,9 @@ struct file_buffer
33803380
char_u *b_p_fex; // 'formatexpr'
33813381
long_u b_p_fex_flags; // flags for 'formatexpr'
33823382
#endif
3383+
#ifdef HAVE_FSYNC
3384+
int b_p_fs; // 'fsync'
3385+
#endif
33833386
#ifdef FEAT_CRYPT
33843387
char_u *b_p_key; // 'key'
33853388
#endif

src/testdir/test_options.vim

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,25 +1681,34 @@ endfunc
16811681

16821682
" Test for setting boolean global-local option value
16831683
func Test_set_boolean_global_local_option()
1684-
setglobal autoread
1685-
setlocal noautoread
1684+
CheckUnix
1685+
1686+
setglobal autoread fsync
1687+
setlocal noautoread nofsync
16861688
call assert_equal(1, &g:autoread)
16871689
call assert_equal(0, &l:autoread)
16881690
call assert_equal(0, &autoread)
1691+
call assert_equal(1, &g:fsync)
1692+
call assert_equal(0, &l:fsync)
1693+
call assert_equal(0, &fsync)
16891694

16901695
" :set {option}< set the effective value of {option} to its global value.
1691-
set autoread<
1696+
set autoread< fsync<
16921697
call assert_equal(1, &l:autoread)
16931698
call assert_equal(1, &autoread)
1699+
call assert_equal(1, &l:fsync)
1700+
call assert_equal(1, &fsync)
16941701

16951702
" :setlocal {option}< removes the local value, so that the global value will be used.
1696-
setglobal noautoread
1697-
setlocal autoread
1698-
setlocal autoread<
1703+
setglobal noautoread nofsync
1704+
setlocal autoread fsync
1705+
setlocal autoread< fsync<
16991706
call assert_equal(-1, &l:autoread)
17001707
call assert_equal(0, &autoread)
1708+
call assert_equal(-1, &l:fsync)
1709+
call assert_equal(0, &fsync)
17011710

1702-
set autoread&
1711+
set autoread& fsync&
17031712
endfunc
17041713

17051714
func Test_set_in_sandbox()

src/undo.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1774,7 +1774,8 @@ u_write_undo(
17741774
#endif
17751775

17761776
#if defined(UNIX) && defined(HAVE_FSYNC)
1777-
if (p_fs && fflush(fp) == 0 && vim_fsync(fd) != 0)
1777+
if ((buf->b_p_fs >= 0 ? buf->b_p_fs : p_fs) && fflush(fp) == 0
1778+
&& vim_fsync(fd) != 0)
17781779
write_ok = FALSE;
17791780
#endif
17801781

0 commit comments

Comments
 (0)