File Coverage

blib/lib/Filesys/POSIX/Mount.pm
Criterion Covered Total %
statement 42 42 100.0
branch 4 4 100.0
condition 1 3 33.3
subroutine 12 12 100.0
pod 5 5 100.0
total 64 66 96.9


line stmt bran cond sub pod time code
1             # Copyright (c) 2014, cPanel, Inc.
2             # All rights reserved.
3             # http://cpanel.net/
4             #
5             # This is free software; you can redistribute it and/or modify it under the same
6             # terms as Perl itself. See the LICENSE file for further details.
7              
8             package Filesys::POSIX::Mount;
9              
10 25     25   83 use strict;
  25         25  
  25         541  
11 25     25   70 use warnings;
  25         25  
  25         467  
12              
13 25     25   72 use Filesys::POSIX::Bits;
  25         28  
  25         5633  
14 25     25   100 use Filesys::POSIX::Module ();
  25         23  
  25         273  
15 25     25   90 use Filesys::POSIX::Path ();
  25         26  
  25         392  
16              
17 25     25   76 use Filesys::POSIX::Error qw(throw);
  25         27  
  25         876  
18              
19 25     25   83 use Carp qw(confess);
  25         28  
  25         8232  
20              
21             my @METHODS = qw(mount unmount statfs fstatfs mountlist);
22              
23             Filesys::POSIX::Module->export_methods( __PACKAGE__, @METHODS );
24              
25             =head1 NAME
26              
27             Filesys::POSIX::Mount - Exposes VFS mounting functionality to L
28              
29             =head1 DESCRIPTION
30              
31             C is a mixin module imported into the L
32             namespace by said module that provides a frontend to the internal VFS. Rather
33             than dealing in terms of mount point vnodes as L does, the
34             system calls provided in this module deal in terms of pathnames.
35              
36             =head1 SYSTEM CALLS
37              
38             =over
39              
40             =item C<$fs-Emount($dev, $path, %opts)>
41              
42             Attach the filesystem device, C<$dev>, to the directory inode specified by
43             C<$path>. The C<%opts> hash can be used to pass mount options to the
44             initialization routines for the device object to be mounted; these options are
45             passed to the C<$dev-Einit()> routine that said filesystem device
46             implements.
47              
48             The filesystem mount record is kept in an ordered list by the VFS, and can be
49             retrieved later using the C<$fs-Estatfs>, or C<$fs-Emountlist> system
50             calls.
51              
52             =cut
53              
54             sub mount {
55 14     14 1 1549 my ( $self, $dev, $path, %opts ) = @_;
56 14         45 my $mountpoint = $self->stat($path);
57 14         43 my $realpath = $self->_find_inode_path($mountpoint);
58              
59 14   33     52 $opts{'fs'} ||= $self;
60              
61 14         43 $dev->init(%opts);
62              
63 12         40 $self->{'vfs'}->mount( $dev, $realpath, $mountpoint, %opts );
64             }
65              
66             =item C<$fs-Eunmount($path)>
67              
68             Attempts to unmount a filesystem mounted at the directory pointed to by
69             C<$path>, performing a number of sanity checks to ensure the safety of the
70             current operation. The following checks are made:
71              
72             =over
73              
74             =item The directory inode is retrieved using C<$fs-Estat>.
75              
76             =item Using Cstatfs>, with the directory inode passed,
77             the VFS is queried to determine if the location given has a filesystem mounted
78             at all. If so, the mount record is kept for reference for the next series of
79             checks.
80              
81             =item The file descriptor table is scanned for open files whose inodes exist on
82             the device found for the mount record queried in the previous step by the VFS.
83             An EBUSY exception is thrown when matching file descriptors are found.
84              
85             =item The current working directory is checked to ensure it is not a reference
86             to a directory inode associated with the mounted device. An EBUSY exception is
87             thrown if the current directory is on the same device that is to be unmounted.
88              
89             =back
90              
91             =cut
92              
93             sub unmount {
94 6     6 1 430 my ( $self, $path ) = @_;
95 6         13 my $mountpoint = $self->stat($path);
96 6         13 my $mount = $self->{'vfs'}->statfs( $mountpoint, 'exact' => 1 );
97              
98             #
99             # First, check for open file descriptors held on the desired device.
100             #
101 6         16 foreach ( $self->{'fds'}->list ) {
102 3         7 my $inode = $self->{'fds'}->lookup($_)->{'inode'};
103              
104 3 100       16 throw &Errno::EBUSY if $mount->{'dev'} eq $inode->{'dev'};
105             }
106              
107             #
108             # Next, check to see if the current working directory's device inode
109             # is the same device as the one being requested for unmounting.
110             #
111 5 100       15 throw &Errno::EBUSY if $mount->{'dev'} eq $self->{'cwd'}->{'dev'};
112              
113 4         9 $self->{'vfs'}->unmount($mount);
114             }
115              
116             =item C<$fs-Estatfs($path)>
117              
118             Returns the mount record for the device associated with the inode specified by
119             $path. The inode is found using C<$fs-Estat>, then queried for by
120             Cstatfs>.
121              
122             =cut
123              
124             sub statfs {
125 3     3 1 859 my ( $self, $path ) = @_;
126 3         9 my $inode = $self->stat($path);
127              
128 3         9 return $self->{'vfs'}->statfs($inode);
129             }
130              
131             =item C<$fs-Efstatfs($fd)>
132              
133             Returns the mount record for the device associated with the inode referenced by
134             the open file descriptor, C<$fd>. The inode is found using C<$fs-Efstat>,
135             then queried for by Cstatfs>.
136              
137             =cut
138              
139             sub fstatfs {
140 3     3 1 1730 my ( $self, $fd ) = @_;
141 3         7 my $inode = $self->fstat($fd);
142              
143 3         9 return $self->{'vfs'}->statfs($inode);
144             }
145              
146             =item C<$fs-Emountlist>
147              
148             Returns a list of records for each filesystem currently mounted, in the order
149             in which they were mounted.
150              
151             =cut
152              
153             sub mountlist {
154 1     1 1 8 shift->{'vfs'}->mountlist;
155             }
156              
157             =back
158              
159             =head1 ANATOMY OF A MOUNT RECORD
160              
161             Mount records are created internally by Cmount>, and
162             are stored as anonymous HASHes. They contain the following attributes:
163              
164             =over
165              
166             =item C
167              
168             Reference to the directory inode (or vnode in the case of multiple filesystems
169             mounted in the same logical location) the filesystem is mounted to.
170              
171             =item C
172              
173             Reference to the mounted filesystem's root directory inode. This is never a
174             vnode.
175              
176             =item C
177              
178             The value of the C flag specified in a call to C<$fs-Emount>. When
179             no value is specified, the value stored is equal to C.
180              
181             =item C
182              
183             A reference to the filesystem device object that was mounted by
184             C<$fs-Emount>.
185              
186             =item C
187              
188             A lowercase string formed by chopping all but the last item in a Perl fully
189             qualified package name corresponding to the type of the device mounted. For
190             instance, an instance of L mounted will result in a value
191             of C<'mem'>.
192              
193             =item C
194              
195             The true, original, and sanitized path of the mount point specified by
196             C<$fs-Emount>.
197              
198             =item C
199              
200             A VFS inode created by Cnew>, containing most
201             attributes of the mounted device's root inode, but with a parent pointing to
202             the mount point inode's parent.
203              
204             =item C
205              
206             A copy of the options passed to C<$fs-Emount>, minus the C option.
207              
208             =back
209              
210             =cut
211              
212             1;
213              
214             __END__