Page MenuHomeFreeBSD

D55595.id172943.diff
No OneTemporary

D55595.id172943.diff

diff --git a/sys/fs/deadfs/dead_vnops.c b/sys/fs/deadfs/dead_vnops.c
--- a/sys/fs/deadfs/dead_vnops.c
+++ b/sys/fs/deadfs/dead_vnops.c
@@ -80,6 +80,7 @@
.vop_write = dead_write,
.vop_fplookup_vexec = VOP_EOPNOTSUPP,
.vop_fplookup_symlink = VOP_EOPNOTSUPP,
+ .vop_delayed_setsize = VOP_NULL,
};
VFS_VOP_VECTOR_REGISTER(dead_vnodeops);
diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c
--- a/sys/fs/nfsclient/nfs_clbio.c
+++ b/sys/fs/nfsclient/nfs_clbio.c
@@ -842,6 +842,7 @@
int bp_cached, n, on, error = 0, error1, save2, wouldcommit;
size_t orig_resid, local_resid;
off_t orig_size, tmp_off;
+ u_quad_t sz;
struct timespec ts;
KASSERT(uio->uio_rw == UIO_WRITE, ("ncl_write mode"));
@@ -1038,12 +1039,12 @@
if (bp != NULL) {
long save;
+ vn_clear_delayed_setsize(vp);
NFSLOCKNODE(np);
- np->n_size = uio->uio_offset + n;
+ sz = np->n_size = uio->uio_offset + n;
np->n_flag |= NMODIFIED;
- np->n_flag &= ~NVNSETSZSKIP;
- vnode_pager_setsize(vp, np->n_size);
NFSUNLOCKNODE(np);
+ vnode_pager_setsize(vp, sz);
save = bp->b_flags & B_CACHE;
bcount = on + n;
@@ -1069,12 +1070,12 @@
bp = nfs_getcacheblk(vp, lbn, bcount, td);
NFSLOCKNODE(np);
if (uio->uio_offset + n > np->n_size) {
- np->n_size = uio->uio_offset + n;
+ sz = np->n_size = uio->uio_offset + n;
np->n_flag |= NMODIFIED;
- np->n_flag &= ~NVNSETSZSKIP;
- vnode_pager_setsize(vp, np->n_size);
}
NFSUNLOCKNODE(np);
+ vn_clear_delayed_setsize(vp);
+ vnode_pager_setsize(vp, sz);
}
if (!bp) {
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -646,7 +646,7 @@
(curthread->td_pflags2 & TDP2_SBPAGES) == 0)
setnsize = true;
else
- np->n_flag |= NVNSETSZSKIP;
+ vn_delay_setsize(vp);
}
if (nsizep == NULL) {
NFSUNLOCKNODE(np);
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -155,7 +155,7 @@
static vop_setextattr_t nfs_setextattr;
static vop_listextattr_t nfs_listextattr;
static vop_deleteextattr_t nfs_deleteextattr;
-static vop_lock1_t nfs_lock;
+static vop_delayed_setsize_t nfs_delayed_setsize;
/*
* Global vfs data structures for nfs
@@ -168,13 +168,13 @@
.vop_advlockasync = nfs_advlockasync,
.vop_close = nfs_close,
.vop_create = nfs_create,
+ .vop_delayed_setsize = nfs_delayed_setsize,
.vop_fsync = nfs_fsync,
.vop_getattr = nfs_getattr,
.vop_getpages = ncl_getpages,
.vop_putpages = ncl_putpages,
.vop_inactive = ncl_inactive,
.vop_link = nfs_link,
- .vop_lock1 = nfs_lock,
.vop_lookup = nfs_lookup,
.vop_mkdir = nfs_mkdir,
.vop_mknod = nfs_mknod,
@@ -331,73 +331,19 @@
*/
static int
-nfs_lock(struct vop_lock1_args *ap)
+nfs_delayed_setsize(struct vop_delayed_setsize_args *ap)
{
struct vnode *vp;
struct nfsnode *np;
u_quad_t nsize;
- int error, lktype;
- bool onfault;
vp = ap->a_vp;
- lktype = ap->a_flags & LK_TYPE_MASK;
- error = VOP_LOCK1_APV(&default_vnodeops, ap);
- if (error != 0 || vp->v_op != &newnfs_vnodeops)
- return (error);
np = VTONFS(vp);
- if (np == NULL)
- return (0);
- NFSLOCKNODE(np);
- if ((np->n_flag & NVNSETSZSKIP) == 0 || (lktype != LK_SHARED &&
- lktype != LK_EXCLUSIVE && lktype != LK_UPGRADE &&
- lktype != LK_TRYUPGRADE)) {
- NFSUNLOCKNODE(np);
- return (0);
- }
- onfault = (ap->a_flags & LK_EATTR_MASK) == LK_NOWAIT &&
- (ap->a_flags & LK_INIT_MASK) == LK_CANRECURSE &&
- (lktype == LK_SHARED || lktype == LK_EXCLUSIVE);
- if (onfault && vp->v_vnlock->lk_recurse == 0) {
- /*
- * Force retry in vm_fault(), to make the lock request
- * sleepable, which allows us to piggy-back the
- * sleepable call to vnode_pager_setsize().
- */
- NFSUNLOCKNODE(np);
- VOP_UNLOCK(vp);
- return (EBUSY);
- }
- if ((ap->a_flags & LK_NOWAIT) != 0 ||
- (lktype == LK_SHARED && vp->v_vnlock->lk_recurse > 0)) {
- NFSUNLOCKNODE(np);
- return (0);
- }
- if (lktype == LK_SHARED) {
- NFSUNLOCKNODE(np);
- VOP_UNLOCK(vp);
- ap->a_flags &= ~(LK_TYPE_MASK | LK_INTERLOCK);
- ap->a_flags |= LK_EXCLUSIVE;
- error = VOP_LOCK1_APV(&default_vnodeops, ap);
- if (error != 0 || vp->v_op != &newnfs_vnodeops)
- return (error);
- if (vp->v_data == NULL)
- goto downgrade;
- MPASS(vp->v_data == np);
+ if (np != NULL) {
NFSLOCKNODE(np);
- if ((np->n_flag & NVNSETSZSKIP) == 0) {
- NFSUNLOCKNODE(np);
- goto downgrade;
- }
- }
- np->n_flag &= ~NVNSETSZSKIP;
- nsize = np->n_size;
- NFSUNLOCKNODE(np);
- vnode_pager_setsize(vp, nsize);
-downgrade:
- if (lktype == LK_SHARED) {
- ap->a_flags &= ~(LK_TYPE_MASK | LK_INTERLOCK);
- ap->a_flags |= LK_DOWNGRADE;
- (void)VOP_LOCK1_APV(&default_vnodeops, ap);
+ nsize = np->n_size;
+ NFSUNLOCKNODE(np);
+ vnode_pager_setsize(vp, nsize);
}
return (0);
}
diff --git a/sys/fs/nfsclient/nfsnode.h b/sys/fs/nfsclient/nfsnode.h
--- a/sys/fs/nfsclient/nfsnode.h
+++ b/sys/fs/nfsclient/nfsnode.h
@@ -160,7 +160,6 @@
#define NWRITEOPENED 0x00040000 /* Has been opened for writing */
#define NHASBEENLOCKED 0x00080000 /* Has been file locked. */
#define NDSCOMMIT 0x00100000 /* Commit is done via the DS. */
-#define NVNSETSZSKIP 0x00200000 /* Skipped vnode_pager_setsize() */
#define NMIGHTBELOCKED 0x00400000 /* Might be file locked. */
#define NNAMEDNOTSUPP 0x00800000 /* Openattr is not supported. */
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -147,6 +147,7 @@
.vop_add_writecount = vop_stdadd_writecount,
.vop_copy_file_range = vop_stdcopy_file_range,
.vop_vput_pair = vop_stdvput_pair,
+ .vop_delayed_setsize = VOP_PANIC,
};
VFS_VOP_VECTOR_REGISTER(default_vnodeops);
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1959,14 +1959,88 @@
return (0);
}
+static int
+vn_lock_delayed_setsize(struct vop_lock1_args *ap)
+{
+ struct vnode *vp;
+ int error, lktype;
+ bool onfault;
+
+ vp = ap->a_vp;
+ lktype = ap->a_flags & LK_TYPE_MASK;
+ error = VOP_LOCK1_APV(&default_vnodeops, ap);
+ if (error != 0 || vp->v_op == &dead_vnodeops)
+ return (error);
+ VI_LOCK(vp);
+ if ((vp->v_iflag & VI_DELAYEDSSZ) == 0 || (lktype != LK_SHARED &&
+ lktype != LK_EXCLUSIVE && lktype != LK_UPGRADE &&
+ lktype != LK_TRYUPGRADE)) {
+ VI_UNLOCK(vp);
+ return (0);
+ }
+ onfault = (ap->a_flags & LK_EATTR_MASK) == LK_NOWAIT &&
+ (ap->a_flags & LK_INIT_MASK) == LK_CANRECURSE &&
+ (lktype == LK_SHARED || lktype == LK_EXCLUSIVE);
+ if (onfault && vp->v_vnlock->lk_recurse == 0) {
+ /*
+ * Force retry in vm_fault(), to make the lock request
+ * sleepable, which allows us to piggy-back the
+ * sleepable call to vnode_pager_setsize().
+ */
+ VI_UNLOCK(vp);
+ VOP_UNLOCK(vp);
+ return (EBUSY);
+ }
+ if ((ap->a_flags & LK_NOWAIT) != 0 ||
+ (lktype == LK_SHARED && vp->v_vnlock->lk_recurse > 0)) {
+ VI_UNLOCK(vp);
+ return (0);
+ }
+ if (lktype == LK_SHARED) {
+ VOP_UNLOCK(vp);
+ ap->a_flags &= ~LK_TYPE_MASK;
+ ap->a_flags |= LK_EXCLUSIVE | LK_INTERLOCK;
+ error = VOP_LOCK1_APV(&default_vnodeops, ap);
+ if (error != 0 || vp->v_op == &dead_vnodeops)
+ return (error);
+ if (vp->v_data == NULL)
+ goto downgrade;
+ MPASS(vp->v_data != NULL);
+ VI_LOCK(vp);
+ if ((vp->v_iflag & VI_DELAYEDSSZ) == 0) {
+ VI_UNLOCK(vp);
+ goto downgrade;
+ }
+ }
+ vp->v_iflag &= ~VI_DELAYEDSSZ;
+ VI_UNLOCK(vp);
+ VOP_DELAYED_SETSIZE(vp);
+downgrade:
+ if (lktype == LK_SHARED) {
+ ap->a_flags &= ~(LK_TYPE_MASK | LK_INTERLOCK);
+ ap->a_flags |= LK_DOWNGRADE;
+ (void)VOP_LOCK1_APV(&default_vnodeops, ap);
+ }
+ return (0);
+}
+
int
_vn_lock(struct vnode *vp, int flags, const char *file, int line)
{
+ struct vop_lock1_args ap;
int error;
VNASSERT((flags & LK_TYPE_MASK) != 0, vp,
("vn_lock: no locktype (%d passed)", flags));
VNPASS(vp->v_holdcnt > 0, vp);
+ if ((vp->v_iflag & VI_DELAYEDSSZ) != 0) {
+ ap.a_gen.a_desc = &vop_lock1_desc;
+ ap.a_vp = vp;
+ ap.a_flags = flags;
+ ap.a_file = file;
+ ap.a_line = line;
+ return (vn_lock_delayed_setsize(&ap));
+ }
error = VOP_LOCK1(vp, flags, file, line);
if (__predict_false(error != 0 || VN_IS_DOOMED(vp)))
return (_vn_lock_fallback(vp, flags, file, line, error));
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -847,6 +847,14 @@
IN struct thread *td;
};
+
+%% delayed_setsize vp E E E
+
+vop_delayed_setsize {
+ IN struct vnode *vp;
+};
+
+
# The VOPs below are spares at the end of the table to allow new VOPs to be
# added in stable branches without breaking the KBI. New VOPs in HEAD should
# be added above these spares. When merging a new VOP to a stable branch,
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -268,6 +268,7 @@
#define VI_DEFINACT 0x0010 /* deferred inactive */
#define VI_FOPENING 0x0020 /* In open, with opening process having the
first right to advlock file */
+#define VI_DELAYEDSSZ 0x0040 /* Delayed setsize */
#define VV_ROOT 0x0001 /* root of its filesystem */
#define VV_ISTTY 0x0002 /* vnode represents a tty */
@@ -1251,6 +1252,36 @@
atomic_load_consume_ptr(&(_vp)->v_data);\
})
+static inline void
+vn_delay_setsize_locked(struct vnode *vp)
+{
+ ASSERT_VI_LOCKED(vp, "delayed_setsize");
+ vp->v_iflag |= VI_DELAYEDSSZ;
+}
+
+static inline void
+vn_delay_setsize(struct vnode *vp)
+{
+ VI_LOCK(vp);
+ vn_delay_setsize_locked(vp);
+ VI_UNLOCK(vp);
+}
+
+static inline void
+vn_clear_delayed_setsize_locked(struct vnode *vp)
+{
+ ASSERT_VI_LOCKED(vp, "delayed_setsize");
+ vp->v_iflag &= ~VI_DELAYEDSSZ;
+}
+
+static inline void
+vn_clear_delayed_setsize(struct vnode *vp)
+{
+ VI_LOCK(vp);
+ vn_clear_delayed_setsize_locked(vp);
+ VI_UNLOCK(vp);
+}
+
#endif /* _KERNEL */
#endif /* !_SYS_VNODE_H_ */

File Metadata

Mime Type
text/plain
Expires
Mon, Mar 2, 7:42 AM (8 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29128041
Default Alt Text
D55595.id172943.diff (9 KB)

Event Timeline