1 /*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 1996, 1997, 1998
5 * Sleepycat Software. All rights reserved.
6 */
7 #include "config.h"
8
9 #ifndef lint
10 static const char sccsid[] = "@(#)mp_fput.c 10.24 (Sleepycat) 9/27/98";
11 #endif /* not lint */
12
13 #ifndef NO_SYSTEM_INCLUDES
14 #include <sys/types.h>
15
16 #include <errno.h>
17 #endif
18
19 #include "db_int.h"
20 #include "shqueue.h"
21 #include "db_shash.h"
22 #include "mp.h"
23 #include "common_ext.h"
24
25 /*
26 * memp_fput --
27 * Mpool file put function.
28 */
29 int
memp_fput(dbmfp,pgaddr,flags)30 memp_fput(dbmfp, pgaddr, flags)
31 DB_MPOOLFILE *dbmfp;
32 void *pgaddr;
33 u_int32_t flags;
34 {
35 BH *bhp;
36 DB_MPOOL *dbmp;
37 MPOOL *mp;
38 int wrote, ret;
39
40 dbmp = dbmfp->dbmp;
41 mp = dbmp->mp;
42
43 MP_PANIC_CHECK(dbmp);
44
45 /* Validate arguments. */
46 if (flags) {
47 if ((ret = __db_fchk(dbmp->dbenv, "memp_fput", flags,
48 DB_MPOOL_CLEAN | DB_MPOOL_DIRTY | DB_MPOOL_DISCARD)) != 0)
49 return (ret);
50 if ((ret = __db_fcchk(dbmp->dbenv, "memp_fput",
51 flags, DB_MPOOL_CLEAN, DB_MPOOL_DIRTY)) != 0)
52 return (ret);
53
54 if (LF_ISSET(DB_MPOOL_DIRTY) && F_ISSET(dbmfp, MP_READONLY)) {
55 __db_err(dbmp->dbenv,
56 "%s: dirty flag set for readonly file page",
57 __memp_fn(dbmfp));
58 return (EACCES);
59 }
60 }
61
62 LOCKREGION(dbmp);
63
64 /* Decrement the pinned reference count. */
65 if (dbmfp->pinref == 0)
66 __db_err(dbmp->dbenv,
67 "%s: put: more blocks returned than retrieved",
68 __memp_fn(dbmfp));
69 else
70 --dbmfp->pinref;
71
72 /*
73 * If we're mapping the file, there's nothing to do. Because we can
74 * stop mapping the file at any time, we have to check on each buffer
75 * to see if the address we gave the application was part of the map
76 * region.
77 */
78 if (dbmfp->addr != NULL && pgaddr >= dbmfp->addr &&
79 (u_int8_t *)pgaddr <= (u_int8_t *)dbmfp->addr + dbmfp->len) {
80 UNLOCKREGION(dbmp);
81 return (0);
82 }
83
84 /* Convert the page address to a buffer header. */
85 bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf));
86
87 /* Set/clear the page bits. */
88 if (LF_ISSET(DB_MPOOL_CLEAN) && F_ISSET(bhp, BH_DIRTY)) {
89 ++mp->stat.st_page_clean;
90 --mp->stat.st_page_dirty;
91 F_CLR(bhp, BH_DIRTY);
92 }
93 if (LF_ISSET(DB_MPOOL_DIRTY) && !F_ISSET(bhp, BH_DIRTY)) {
94 --mp->stat.st_page_clean;
95 ++mp->stat.st_page_dirty;
96 F_SET(bhp, BH_DIRTY);
97 }
98 if (LF_ISSET(DB_MPOOL_DISCARD))
99 F_SET(bhp, BH_DISCARD);
100
101 /*
102 * Check for a reference count going to zero. This can happen if the
103 * application returns a page twice.
104 */
105 if (bhp->ref == 0) {
106 __db_err(dbmp->dbenv, "%s: page %lu: unpinned page returned",
107 __memp_fn(dbmfp), (u_long)bhp->pgno);
108 UNLOCKREGION(dbmp);
109 return (EINVAL);
110 }
111
112 /*
113 * If more than one reference to the page, we're done. Ignore the
114 * discard flags (for now) and leave it at its position in the LRU
115 * chain. The rest gets done at last reference close.
116 */
117 if (--bhp->ref > 0) {
118 UNLOCKREGION(dbmp);
119 return (0);
120 }
121
122 /* Move the buffer to the head/tail of the LRU chain. */
123 SH_TAILQ_REMOVE(&mp->bhq, bhp, q, __bh);
124 if (F_ISSET(bhp, BH_DISCARD))
125 SH_TAILQ_INSERT_HEAD(&mp->bhq, bhp, q, __bh);
126 else
127 SH_TAILQ_INSERT_TAIL(&mp->bhq, bhp, q);
128
129 /*
130 * If this buffer is scheduled for writing because of a checkpoint, we
131 * need to write it (if we marked it dirty), or update the checkpoint
132 * counters (if we didn't mark it dirty). If we try to write it and
133 * can't, that's not necessarily an error, but set a flag so that the
134 * next time the memp_sync function runs we try writing it there, as
135 * the checkpoint application better be able to write all of the files.
136 */
137 if (F_ISSET(bhp, BH_WRITE))
138 if (F_ISSET(bhp, BH_DIRTY)) {
139 if (__memp_bhwrite(dbmp,
140 dbmfp->mfp, bhp, NULL, &wrote) != 0 || !wrote)
141 F_SET(mp, MP_LSN_RETRY);
142 } else {
143 F_CLR(bhp, BH_WRITE);
144
145 --dbmfp->mfp->lsn_cnt;
146 --mp->lsn_cnt;
147 }
148
149 UNLOCKREGION(dbmp);
150 return (0);
151 }
152