%% fileadv.tex
%%
-%% Copyright (C) 2000-2009 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2010 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Un preambolo",
\textit{lease breaker} rimaste bloccate proseguono automaticamente.
-\index{file!dnotify|(}
+\itindbeg{dnotify}
Benché possa risultare utile per sincronizzare l'accesso ad uno stesso file da
parte di più processi, l'uso dei \textit{file lease} non consente comunque di
nelle precedenti. Se si vuole rimuovere la notifica si deve invece
specificare un valore nullo.
-\index{file!inotify|(}
+\itindbeg{inotify}
Il maggiore problema di \textit{dnotify} è quello della scalabilità: si deve
usare un file descriptor per ciascuna directory che si vuole tenere sotto
quella di \textit{dnotify} viene considerata una interfaccia di usabilità
problematica.
-\index{file!dnotify|)}
+\itindend{dnotify}
Per risolvere i problemi appena illustrati è stata introdotta una nuova
interfaccia per l'osservazione delle modifiche a file o directory, chiamata
dei campi \var{wd}, \var{mask}, \var{cookie}, e \var{name}) questi vengono
raggruppati in un solo evento.
-\index{file!inotify|)}
+\itindend{inotify}
% TODO trattare fanotify, vedi http://lwn.net/Articles/339399/ e
% http://lwn.net/Articles/343346/
operazioni, usando un vettore di \textit{control block}. Tramite questo campo
si specifica quale è la natura di ciascuna di esse.
-\begin{figure}[!htb]
- \footnotesize \centering
- \begin{minipage}[c]{15cm}
- \includestruct{listati/sigevent.h}
- \end{minipage}
- \normalsize
- \caption{La struttura \structd{sigevent}, usata per specificare le modalità
- di notifica degli eventi relativi alle operazioni di I/O asincrono.}
- \label{fig:file_sigevent}
-\end{figure}
-
Infine il campo \var{aio\_sigevent} è una struttura di tipo \struct{sigevent}
-che serve a specificare il modo in cui si vuole che venga effettuata la
-notifica del completamento delle operazioni richieste. La struttura è
-riportata in fig.~\ref{fig:file_sigevent}; il campo \var{sigev\_notify} è
-quello che indica le modalità della notifica, esso può assumere i tre valori:
-\begin{basedescript}{\desclabelwidth{2.6cm}}
-\item[\const{SIGEV\_NONE}] Non viene inviata nessuna notifica.
-\item[\const{SIGEV\_SIGNAL}] La notifica viene effettuata inviando al processo
- chiamante il segnale specificato da \var{sigev\_signo}; se il gestore di
- questo è stato installato con \const{SA\_SIGINFO} gli verrà restituito il
- valore di \var{sigev\_value} (la cui definizione è in
- fig.~\ref{fig:sig_sigval}) come valore del campo \var{si\_value} di
- \struct{siginfo\_t}.
-\item[\const{SIGEV\_THREAD}] La notifica viene effettuata creando un nuovo
- \itindex{thread} \textit{thread} che esegue la funzione specificata da
- \var{sigev\_notify\_function} con argomento \var{sigev\_value}, e con gli
- attributi specificati da \var{sigev\_notify\_attribute}.
-\end{basedescript}
+(illustrata in in fig.~\ref{fig:struct_sigevent}) che serve a specificare il
+modo in cui si vuole che venga effettuata la notifica del completamento delle
+operazioni richieste; per la trattazione delle modalità di utilizzo della
+stessa si veda quanto già visto in proposito in sez.~\ref{sec:sig_timer_adv}.
Le due funzioni base dell'interfaccia per l'I/O asincrono sono
\funcd{aio\_read} ed \funcd{aio\_write}. Esse permettono di richiedere una
\begin{figure}[htb]
\centering
- \includegraphics[width=14cm]{img/mmap_layout}
+ \includegraphics[width=12cm]{img/mmap_layout}
\caption{Disposizione della memoria di un processo quando si esegue la
mappatura in memoria di un file.}
\label{fig:file_mmap_layout}
Si tenga presente infine che queste funzioni operano sui file con
l'interfaccia dei file descriptor, e non è consigliabile mescolarle con
-l'interfaccia classica dei \textit{file stream}; a causa delle bufferizzazioni
-interne di quest'ultima infatti si potrebbero avere risultati indefiniti e non
-corrispondenti a quanto aspettato.
+l'interfaccia classica dei \textit{file stream} di
+cap.~\ref{cha:files_std_interface}; a causa delle bufferizzazioni interne di
+quest'ultima infatti si potrebbero avere risultati indefiniti e non
+corrispondenti a quanto aspettato.
Come per le normali operazioni di lettura e scrittura, anche per l'\textsl{I/O
vettorizzato} si pone il problema di poter effettuare le operazioni in
-maniera atomica a partire da un certa posizione sul file; per questo motivo a
+maniera atomica a partire da un certa posizione sul file. Per questo motivo a
partire dal kernel 2.6.30 sono state introdotte anche per l'\textsl{I/O
vettorizzato} le analoghe delle funzioni \func{pread} e \func{pwrite} (vedi
-sez.~\ref{sec:file_read} e \ref{sec:file_write}) che consentono di effettuare
-letture e scritture vettorizzate a partire da una certa posizione. Le due
-funzioni sono \funcd{preadv} e \func{pwritev} ed i rispettivi prototipi sono:
+sez.~\ref{sec:file_read} e \ref{sec:file_write}); le due funzioni sono
+\funcd{preadv} e \func{pwritev} ed i rispettivi prototipi sono:\footnote{le
+ due funzioni sono analoghe alle omonime presenti in BSD; le \textit{system
+ call} usate da Linux (introdotte a partire dalla versione 2.6.30)
+ utilizzano degli argomenti diversi per problemi collegati al formato a 64
+ bit dell'argomento \param{offset}, che varia a seconda delle architetture,
+ ma queste differenze vengono gestite dalle funzioni di librerie di libreria
+ che mantengono l'interfaccia delle analoghe tratte da BSD.}
+\begin{functions}
+ \headdecl{sys/uio.h}
+
+ \funcdecl{int preadv(int fd, const struct iovec *vector, int count, off\_t
+ offset)}
+ \funcdecl{int pwritev(int fd, const struct iovec *vector, int count, off\_t
+ offset)}
+
+ Eseguono una lettura o una scrittura vettorizzata a partire da una data
+ posizione sul file.
+
+ \bodydesc{Le funzioni hanno gli stessi valori di ritorno delle
+ corrispondenti \func{readv} e \func{writev}; anche gli eventuali errori
+ sono gli stessi già visti in precedenza, ma ad essi si possono aggiungere
+ per \var{errno} anche i valori:
+ \begin{errlist}
+ \item[\errcode{EOVERFLOW}] \param{offset} ha un valore che non può essere
+ usato come \ctyp{off\_t}.
+ \item[\errcode{ESPIPE}] \param{fd} è associato ad un socket o una pipe.
+ \end{errlist}
+}
+\end{functions}
+
+Le due funzioni eseguono rispettivamente una lettura o una scrittura
+vettorizzata a partire dalla posizione \param{offset} sul file indicato
+da \param{fd}, la posizione corrente sul file, come vista da eventuali altri
+processi che vi facciano riferimento, non viene alterata. A parte la presenza
+dell'ulteriore argomento il comportamento delle funzioni è identico alle
+precedenti \func{readv} e \func{writev}.
-% TODO verificare cosa succederà a preadv e pwritev o alla nuova niovec
-% vedi http://lwn.net/Articles/164887/
-% inserite nel kernel 2.6.30, vedi http://lwn.net/Articles/326818/
+Con l'uso di queste funzioni si possono evitare eventuali
+\itindex{race~condition} \textit{race condition} quando si deve eseguire la
+una operazione di lettura e scrittura vettorizzata a partire da una certa
+posizione su un file, mentre al contempo si possono avere in concorrenza
+processi che utilizzano lo stesso file descriptor (si ricordi quanto visto in
+sez.~\ref{sec:file_adv_func}) con delle chiamate a \func{lseek}.
alcune funzioni specialistiche che permettono di ottimizzare le prestazioni in
questo tipo di situazioni.
-La prima funzione che si pone l'obiettivo di ottimizzare il trasferimento dei
-dati fra due file descriptor è \funcd{sendfile};\footnote{la funzione è stata
+La prima funzione che è stata ideata per ottimizzare il trasferimento dei dati
+fra due file descriptor è \func{sendfile};\footnote{la funzione è stata
introdotta con i kernel della serie 2.2, e disponibile dalle \acr{glibc}
2.1.} la funzione è presente in diverse versioni di Unix,\footnote{la si
ritrova ad esempio in FreeBSD, HPUX ed altri Unix.} ma non è presente né in
POSIX.1-2001 né in altri standard,\footnote{pertanto si eviti di utilizzarla
se si devono scrivere programmi portabili.} per cui per essa vengono
-utilizzati prototipi e semantiche differenti; nel caso di Linux il suo
-prototipo è:
+utilizzati prototipi e semantiche differenti; nel caso di Linux il prototipo
+di \funcd{sendfile} è:
\begin{functions}
\headdecl{sys/sendfile.h}
La funzione copia direttamente \param{count} byte dal file descriptor
\param{in\_fd} al file descriptor \param{out\_fd}; in caso di successo
funzione ritorna il numero di byte effettivamente copiati da \param{in\_fd} a
-\param{out\_fd} o $-1$ in caso di errore, come le ordinarie \func{read} e
+\param{out\_fd} o $-1$ in caso di errore; come le ordinarie \func{read} e
\func{write} questo valore può essere inferiore a quanto richiesto con
\param{count}.
casi l'uso di \func{sendfile} darà luogo ad un errore di \errcode{EINVAL}.
Nonostante ci possano essere casi in cui \func{sendfile} non migliora le
-prestazioni, le motivazioni addotte non convincono del tutto e resta il dubbio
-se la scelta di disabilitarla sempre per il trasferimento di dati fra file di
-dati sia davvero corretta. Se ci sono peggioramenti di prestazioni infatti si
-può sempre fare ricorso all'uso successivo di, ma lasciare a disposizione la
-funzione consentirebbe se non altro, anche in assenza di guadagni di
-prestazioni, di semplificare la gestione della copia dei dati fra file,
-evitando di dover gestire l'allocazione di un buffer temporaneo per il loro
-trasferimento; inoltre si avrebbe comunque il vantaggio di evitare inutili
-trasferimenti di dati da kernel space a user space e viceversa.
-
-Questo dubbio si può comunque ritenere superato con l'introduzione, avvenuto a
-partire dal kernel 2.6.17, della nuova system call \func{splice}. Lo scopo di
-questa funzione è quello di fornire un meccanismo generico per il
+prestazioni, resta il dubbio se la scelta di disabilitarla sempre per il
+trasferimento fra file di dati sia davvero corretta. Se ci sono peggioramenti
+di prestazioni infatti si può sempre fare ricorso al metodo ordinario, ma
+lasciare a disposizione la funzione consentirebbe se non altro di semplificare
+la gestione della copia dei dati fra file, evitando di dover gestire
+l'allocazione di un buffer temporaneo per il loro trasferimento.
+
+Questo dubbio si può comunque ritenere superato con l'introduzione, avvenuta a
+partire dal kernel 2.6.17, della nuova \textit{system call} \func{splice}. Lo
+scopo di questa funzione è quello di fornire un meccanismo generico per il
trasferimento di dati da o verso un file utilizzando un buffer gestito
internamente dal kernel. Descritta in questi termini \func{splice} sembra
semplicemente un ``\textsl{dimezzamento}'' di \func{sendfile}.\footnote{nel
\label{tab:splice_flag}
\end{table}
-\footnotetext{per una maggiore efficienza \func{splice} usa quando possibile i
- meccanismi della memoria virtuale per eseguire i trasferimenti di dati (in
- maniera analoga a \func{mmap}), qualora le pagine non possano essere
- spostate dalla pipe o il buffer non corrisponda a pagine intere esse saranno
- comunque copiate.}
+\footnotetext[120]{per una maggiore efficienza \func{splice} usa quando
+ possibile i meccanismi della memoria virtuale per eseguire i trasferimenti
+ di dati (in maniera analoga a \func{mmap}), qualora le pagine non possano
+ essere spostate dalla pipe o il buffer non corrisponda a pagine intere esse
+ saranno comunque copiate.}
-\footnotetext{questa opzione consente di utilizzare delle opzioni di gestione
- dei socket che permettono di ottimizzare le trasmissioni via rete, si veda
- la descrizione di \const{TCP\_CORK} in sez.~\ref{sec:sock_tcp_udp_options} e
- quella di \const{MSG\_MORE} in sez.~\ref{sec:net_sendmsg}.}
+\footnotetext[121]{questa opzione consente di utilizzare delle opzioni di
+ gestione dei socket che permettono di ottimizzare le trasmissioni via rete,
+ si veda la descrizione di \const{TCP\_CORK} in
+ sez.~\ref{sec:sock_tcp_udp_options} e quella di \const{MSG\_MORE} in
+ sez.~\ref{sec:net_sendmsg}.}
\footnotetext{questo significa che la cache delle pagine e i dati su disco
potranno differire, e che l'applicazione non potrà modificare quest'area di
flag, che si ricordi servono solo a dare suggerimenti al kernel, permette in
genere di migliorare le prestazioni.
-Come accennato con l'introduzione di \func{splice} sono state realizzate altre
-due system call, \func{vmsplice} e \func{tee}, che utilizzano la stessa
-infrastruttura e si basano sullo stesso concetto di manipolazione e
+Come accennato con l'introduzione di \func{splice} sono state realizzate anche
+altre due \textit{system call}, \func{vmsplice} e \func{tee}, che utilizzano
+la stessa infrastruttura e si basano sullo stesso concetto di manipolazione e
trasferimento di dati attraverso un buffer in kernel space; benché queste non
attengono strettamente ad operazioni di trasferimento dati fra file
-descriptor, le tratteremo qui.
+descriptor, le tratteremo qui, essendo strettamente correlate fra loro.
La prima funzione, \funcd{vmsplice}, è la più simile a \func{splice} e come
-indica il suo nome consente di trasferire i dati dalla memoria di un processo
-verso una \textit{pipe}, il suo prototipo è:
+indica il suo nome consente di trasferire i dati dalla memoria virtuale di un
+processo (ad esempio per un file mappato in memoria) verso una \textit{pipe};
+il suo prototipo è:
\begin{functions}
\headdecl{fcntl.h}
\headdecl{sys/uio.h}
}
\end{functions}
-La \textit{pipe} dovrà essere specificata tramite il file descriptor
-corrispondente al suo capo aperto in scrittura (di nuovo si faccia riferimento
-a sez.~\ref{sec:ipc_unix}), mentre per indicare quali zone di memoria devono
-essere trasferita si deve utilizzare un vettore di strutture \struct{iovec}
-(vedi fig.~\ref{fig:file_iovec}), con le stesse con cui le si usano per l'I/O
-vettorizzato; le dimensioni del suddetto vettore devono essere passate
-nell'argomento \param{nr\_segs} che indica il numero di segmenti di memoria da
-trasferire. Sia per il vettore che per il valore massimo di \param{nr\_segs}
-valgono le stesse limitazioni illustrate in sez.~\ref{sec:file_multiple_io}.
+La \textit{pipe} indicata da \param{fd} dovrà essere specificata tramite il
+file descriptor corrispondente al suo capo aperto in scrittura (di nuovo si
+faccia riferimento a sez.~\ref{sec:ipc_unix}), mentre per indicare quali
+segmenti della memoria del processo devono essere trasferiti verso di essa si
+dovrà utilizzare un vettore di strutture \struct{iovec} (vedi
+fig.~\ref{fig:file_iovec}), esattamente con gli stessi criteri con cui le si
+usano per l'I/O vettorizzato, indicando gli indirizzi e le dimensioni di
+ciascun segmento di memoria su cui si vuole operare; le dimensioni del
+suddetto vettore devono essere passate nell'argomento \param{nr\_segs} che
+indica il numero di segmenti di memoria da trasferire. Sia per il vettore che
+per il valore massimo di \param{nr\_segs} valgono le stesse limitazioni
+illustrate in sez.~\ref{sec:file_multiple_io}.
In caso di successo la funzione ritorna il numero di byte trasferiti sulla
-pipe, in generale (se i dati una volta creati non devono essere riutilizzati)
-è opportuno utilizzare il flag \const{SPLICE\_F\_GIFT}; questo fa si che il
-kernel possa rimuovere le relative pagine dallo spazio degli indirizzi del
-processo, e scaricarle nella cache, così che queste possono essere utilizzate
-immediatamente senza necessità di eseguire una copia dei dati che contengono.
+\textit{pipe}. In generale, se i dati una volta creati non devono essere
+riutilizzati (se cioè l'applicazione che chiama \func{vmsplice} non
+modificherà più la memoria trasferita), è opportuno utilizzare
+per \param{flag} il valore \const{SPLICE\_F\_GIFT}; questo fa sì che il kernel
+possa rimuovere le relative pagine dalla cache della memoria virtuale, così
+che queste possono essere utilizzate immediatamente senza necessità di
+eseguire una copia dei dati che contengono.
La seconda funzione aggiunta insieme a \func{splice} è \func{tee}, che deve il
suo nome all'omonimo comando in user space, perché in analogia con questo
destinazione; a differenza di quanto avviene con \func{read} i dati letti con
\func{tee} da \func{fd\_in} non vengono \textsl{consumati} e restano
disponibili sulla \textit{pipe} per una successiva lettura (di nuovo per il
-comportamento delle \textit{pipe} si veda sez.~\ref{sec:ipc_unix}).
+comportamento delle \textit{pipe} si veda sez.~\ref{sec:ipc_unix}). Al
+momento\footnote{quello della stesura di questo paragrafo, avvenuta il Gennaio
+ 2010, in futuro potrebbe essere implementato anche \const{SPLICE\_F\_MORE}.}
+il solo valore utilizzabile per \param{flag}, fra quelli elencati in
+tab.~\ref{tab:splice_flag}, è \const{SPLICE\_F\_NONBLOCK} che rende la
+funzione non bloccante.
La funzione restituisce il numero di byte copiati da una \textit{pipe}
all'altra (o $-1$ in caso di errore), un valore nullo indica che non ci sono
\index{memoria~virtuale} memoria virtuale ed il meccanismo della
\index{paginazione} paginazione per cui la lettura viene eseguita in blocchi
corrispondenti alle dimensioni delle pagine di memoria, ed i valori di
-\param{offset} e \param{count} arrotondati di conseguenza.
+\param{offset} e \param{count} vengono arrotondati di conseguenza.
La funzione estende quello che è un comportamento normale del kernel che
quando si legge un file, aspettandosi che l'accesso prosegua, esegue sempre
una lettura preventiva di una certa quantità di dati; questo meccanismo di
lettura anticipata viene chiamato \textit{read-ahead}, da cui deriva il nome
-della funzione. La funzione, per ottimizzare gli accessi a disco, effettua la
-lettura in cache della sezione richiesta e si blocca fintanto che questa non
-viene completata. La posizione corrente sul file non viene modificata ed
-indipendentemente da quanto indicato con \param{count} la lettura dei dati si
-interrompe una volta raggiunta la fine del file.
+della funzione. La funzione \func{readahead}, per ottimizzare gli accessi a
+disco, effettua la lettura in cache della sezione richiesta e si blocca
+fintanto che questa non viene completata. La posizione corrente sul file non
+viene modificata ed indipendentemente da quanto indicato con \param{count} la
+lettura dei dati si interrompe una volta raggiunta la fine del file.
Si può utilizzare questa funzione per velocizzare le operazioni di lettura
-all'interno del programma tutte le volte che si conosce in anticipo quanti
-dati saranno necessari in seguito. Si potrà così concentrare in un unico
-momento (ad esempio in fase di inizializzazione) la lettura, così da ottenere
-una migliore risposta nelle operazioni successive.
+all'interno di un programma tutte le volte che si conosce in anticipo quanti
+dati saranno necessari nelle elaborazioni successive. Si potrà così
+concentrare in un unico momento (ad esempio in fase di inizializzazione) la
+lettura dei dati da disco, così da ottenere una migliore velocità di risposta
+nelle operazioni successive.
\itindend{read-ahead}
Il concetto di \func{readahead} viene generalizzato nello standard
-POSIX.1-2001 dalla funzione \funcd{posix\_fadvise},\footnote{anche se
+POSIX.1-2001 dalla funzione \func{posix\_fadvise},\footnote{anche se
l'argomento \param{len} è stato modificato da \ctyp{size\_t} a \ctyp{off\_t}
nella revisione POSIX.1-2003 TC5.} che consente di ``\textsl{avvisare}'' il
kernel sulle modalità con cui si intende accedere nel futuro ad una certa
porzione di un file,\footnote{la funzione però è stata introdotta su Linux
solo a partire dal kernel 2.5.60.} così che esso possa provvedere le
-opportune ottimizzazioni; il suo prototipo, che può è disponibile solo se si
-definisce la macro \macro{\_XOPEN\_SOURCE} ad almeno 600, è:
+opportune ottimizzazioni; il prototipo di \funcd{posix\_fadvise}, che è
+disponibile soltanto se è stata definita la macro \macro{\_XOPEN\_SOURCE} ad
+valore di almeno 600, è:
\begin{functions}
\headdecl{fcntl.h}
Come \func{madvise} anche \func{posix\_fadvise} si appoggia al sistema della
memoria virtuale ed al meccanismo standard del \textit{read-ahead} utilizzato
-dal kernel; in particolare con \const{POSIX\_FADV\_SEQUENTIAL} si raddoppia la
-dimensione dell'ammontare di dati letti preventivamente rispetto al default,
-aspettandosi appunto una lettura sequenziale che li utilizzerà, mentre con
-\const{POSIX\_FADV\_RANDOM} si disabilita del tutto il suddetto meccanismo,
-dato che con un accesso del tutto casuale è inutile mettersi a leggere i dati
-immediatamente successivi gli attuali; infine l'uso di
-\const{POSIX\_FADV\_NORMAL} consente di riportarsi al comportamento di
-default.
+dal kernel; in particolare utilizzando il valore
+\const{POSIX\_FADV\_SEQUENTIAL} si raddoppia la dimensione dell'ammontare di
+dati letti preventivamente rispetto al default, aspettandosi appunto una
+lettura sequenziale che li utilizzerà, mentre con \const{POSIX\_FADV\_RANDOM}
+si disabilita del tutto il suddetto meccanismo, dato che con un accesso del
+tutto casuale è inutile mettersi a leggere i dati immediatamente successivi
+gli attuali; infine l'uso di \const{POSIX\_FADV\_NORMAL} consente di
+riportarsi al comportamento di default.
Le due modalità \const{POSIX\_FADV\_NOREUSE} e \const{POSIX\_FADV\_WILLNEED}
fino al kernel 2.6.18 erano equivalenti, a partire da questo kernel la prima
-viene non ha più alcune effetto, mentre la seconda dà inizio ad una lettura in
+viene non ha più alcun effetto, mentre la seconda dà inizio ad una lettura in
cache della regione del file indicata. La quantità di dati che verranno letti
è ovviamente limitata in base al carico che si viene a creare sul sistema
della memoria virtuale, ma in genere una lettura di qualche megabyte viene
Sia \func{posix\_fadvise} che \func{readahead} attengono alla ottimizzazione
dell'accesso in lettura; lo standard POSIX.1-2001 prevede anche una funzione
-specifica per le operazioni di scrittura, \func{posix\_fallocate},\footnote{la
- funzione è stata introdotta a partire dalle glibc 2.1.94.} che consente di
-preallocare dello spazio disco per assicurarsi che una seguente scrittura non
-fallisca, il suo prototipo, anch'esso disponibile solo se si definisce la
-macro \macro{\_XOPEN\_SOURCE} ad almeno 600, è:
+specifica per le operazioni di scrittura,
+\funcd{posix\_fallocate},\footnote{la funzione è stata introdotta a partire
+ dalle glibc 2.1.94.} che consente di preallocare dello spazio disco per
+assicurarsi che una seguente scrittura non fallisca, il suo prototipo,
+anch'esso disponibile solo se si definisce la macro \macro{\_XOPEN\_SOURCE} ad
+almeno 600, è:
\begin{functions}
\headdecl{fcntl.h}
}
\end{functions}
-La funzione si assicura che venga allocato sufficiente spazio disco perché sia
+La funzione assicura che venga allocato sufficiente spazio disco perché sia
possibile scrivere sul file indicato dall'argomento \param{fd} nella regione
che inizia dalla posizione \param{offset} e si estende per \param{len} byte;
-se questa si estende oltre la fine del file le dimensioni di quest'ultimo
-saranno incrementate di conseguenza. Dopo aver eseguito con successo la
-funzione è garantito che una scrittura nella regione indicata non fallirà per
-mancanza di spazio disco.
-
-% TODO controllare la trattazione della nuova funzionalità di preallocazione
-
-% TODO documentare \func{posix\_fadvise}
-% vedi http://insights.oetiker.ch/linux/fadvise.html
-% questo tread? http://www.ussg.iu.edu/hypermail/linux/kernel/0703.1/0032.html
-
-% TODO documentare \func{fallocate}, introdotta con il 2.6.23
-% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/
-% http://kernelnewbies.org/Linux_2_6_23
-% \func{fallocate} con il 2.6.25 supporta pure XFS
-
-Infine a partire dal kernel 2.6.23 è stata introdotta la nuova system call
-\funcd{fallocate}, che consente di realizzare direttamente all'interno del
-kernel le funzionalità di \func{posix\_fallocate}. Trattandosi di una funzione
-di servizio questa non è stata definita come funzione di libreria e pertanto
-può essere invocata indirettamente con l'ausilio di \func{syscall} (vedi
-sez.~\ref{sec:intro_syscall}; il suo prototipo è:
-
+se questa regione si estende oltre la fine del file le dimensioni di
+quest'ultimo saranno incrementate di conseguenza. Dopo aver eseguito con
+successo la funzione è garantito che una successiva scrittura nella regione
+indicata non fallirà per mancanza di spazio disco. La funzione non ha nessun
+effetto né sul contenuto, né sulla posizione corrente del file.
+
+Ci si può chiedere a cosa possa servire una funzione come
+\func{posix\_fallocate} dato che è sempre possibile ottenere l'effetto voluto
+eseguendo esplicitamente sul file la scrittura\footnote{usando \funcd{pwrite}
+ per evitare spostamenti della posizione corrente sul file.} di una serie di
+zeri per l'estensione di spazio necessaria qualora il \itindex{sparse~file}
+file debba essere esteso o abbia dei \index{file!\textit{hole}}
+buchi.\footnote{si ricordi che occorre scrivere per avere l'allocazione e che
+ l'uso di \func{truncate} per estendere un file creerebbe soltanto uno
+ \itindex{sparse~file} \textit{sparse file} (vedi sez.~\ref{sec:file_lseek})
+ senza una effettiva allocazione dello spazio disco.} In realtà questa è la
+modalità con cui la funzione veniva realizzata nella prima versione fornita
+dalle \acr{glibc}, per cui la funzione costituiva in sostanza soltanto una
+standardizzazione delle modalità di esecuzione di questo tipo di allocazioni.
+
+Questo metodo, anche se funzionante, comporta però l'effettiva esecuzione una
+scrittura su tutto lo spazio disco necessario, da fare al momento della
+richiesta di allocazione, pagandone il conseguente prezzo in termini di
+prestazioni; il tutto quando in realtà servirebbe solo poter riservare lo
+spazio per poi andarci a scrivere, una sola volta, quando il contenuto finale
+diventa effettivamente disponibile.
+
+Per poter fare tutto questo è però necessario il supporto da parte del kernel,
+e questo è divenuto disponibile solo a partire dal kernel 2.6.23 in cui è
+stata introdotta la nuova \textit{system call} \func{fallocate},\footnote{non
+ è detto che la funzione sia disponibile per tutti i filesystem, ad esempio
+ per XFS il supporto è stato introdotto solo a partire dal kernel 2.6.25.}
+che consente di realizzare direttamente all'interno del kernel l'allocazione
+dello spazio disco così da poter realizzare una versione di
+\func{posix\_fallocate} con prestazioni molto più elevate.\footnote{nelle
+ \acr{glibc} la nuova \textit{system call} viene sfruttata per la
+ realizzazione di \func{posix\_fallocate} a partire dalla versione 2.10.}
+
+Trattandosi di una funzione di servizio, ed ovviamente disponibile
+esclusivamente su Linux, inizialmente \funcd{fallocate} non era stata definita
+come funzione di libreria,\footnote{pertanto poteva essere invocata soltanto
+ in maniera indiretta con l'ausilio di \func{syscall}, vedi
+ sez.~\ref{sec:intro_syscall}, come \code{long fallocate(int fd, int mode,
+ loff\_t offset, loff\_t len)}.} ma a partire dalle \acr{glibc} 2.10 è
+ stato fornito un supporto esplicito; il suo prototipo è:
\begin{functions}
- \headdecl{linux/falloc.h}
- \funcdecl{long fallocate(int fd, int mode, loff\_t offset, loff\_t len)}
+ \headdecl{linux/fcntl.h}
+
+ \funcdecl{int fallocate(int fd, int mode, off\_t offset, off\_t len)}
Prealloca dello spazio disco per un file.
}
\end{functions}
+La funzione prende gli stessi argomenti di \func{posix\_fallocate} con lo
+stesso significato, a cui si aggiunge l'argomento \param{mode} che indica le
+modalità di allocazione; al momento quest'ultimo può soltanto essere nullo o
+assumere il valore \const{FALLOC\_FL\_KEEP\_SIZE} che richiede che la
+dimensione del file\footnote{quella ottenuta nel campo \var{st\_size} di una
+ struttura \struct{stat} dopo una chiamata a \texttt{fstat}.} non venga
+modificata anche quando la somma di \param{offset} e \param{len} eccede la
+dimensione corrente.
+
+Se \param{mode} è nullo invece la dimensione totale del file in caso di
+estensione dello stesso viene aggiornata, come richiesto per
+\func{posix\_fallocate}, ed invocata in questo modo si può considerare
+\func{fallocate} come l'implementazione ottimale di \func{posix\_fallocate} a
+livello di kernel.
+
+% vedi http://lwn.net/Articles/226710/ e http://lwn.net/Articles/240571/
+% http://kernelnewbies.org/Linux_2_6_23
+
+
%\subsection{L'utilizzo delle porte di I/O}
% LocalWords: only ETXTBSY DENYWRITE ENODEV filesystem EPERM EXEC noexec table
% LocalWords: ENFILE lenght segment violation SIGSEGV FIXED msync munmap copy
% LocalWords: DoS Denial Service EXECUTABLE NORESERVE LOCKED swapping stack fs
-% LocalWords: GROWSDOWN ANON GiB POPULATE prefaulting SIGBUS fifo VME fork old
+% LocalWords: GROWSDOWN ANON POPULATE prefaulting SIGBUS fifo VME fork old
% LocalWords: exec atime ctime mtime mprotect addr EACCESS mremap address new
% LocalWords: long MAYMOVE realloc VMA virtual Ingo Molnar remap pages pgoff
% LocalWords: dall' fault cache linker prelink advisory discrectionary lock fl
% LocalWords: nwrite segs patch readahead posix fadvise TC advice FADV NORMAL
% LocalWords: SEQUENTIAL NOREUSE WILLNEED DONTNEED streaming fallocate EFBIG
% LocalWords: POLLRDHUP half close pwait Gb madvise MADV ahead REMOVE tmpfs
-% LocalWords: DONTFORK DOFORK shmfs preadv pwritev syscall linux loff
+% LocalWords: DONTFORK DOFORK shmfs preadv pwritev syscall linux loff head XFS
+% LocalWords: MERGEABLE EOVERFLOW prealloca hole FALLOC KEEP stat fstat
%%% Local Variables: